I have the problem. predict() method returns NA. My plan is:

  1. Read data from file and separate data to 2 sets: test and train

  2. Remove column with NA fraction over 95%

  3. Replace NA values with mean value in each column

  4. if(column has more than 50 levels) then read comment to changeFactors() method, feature selection, here I choose 5 features with greatest importance rank.

  5. Build the model and perform predict.

As a result NA values accures in final vector. Could anybody explain to me what I'm doing wrong?

Sorry for the code quality, I know it's horrible


#read data from file and separate it to 2 sets: train and test
data <- read.csv("train.txt", header=T, sep=" ")
data <- train[,c(ncol(data), 1:(ncol(data) - 1))]
train <- data[ids,]
testSet <- data[-ids,]

#select columns with NA fraction over 95%
stat <- apply(train ,2, function(col) mean(is.na(col))) 
stat <- as.data.frame(stat)
stat$names <-  rownames(stat)
colsWithoutNAColumns <- stat[stat$stat < 0.95, "names"]

#replace NA values with mean value in each column
train <- train[, colsWithoutNAColumns]
train$y <- as.factor(train$y)
for(i in 1:ncol(train)){
   col <- train[,i]
      col[is.na(col)] <- getmode(col)
      col[is.na(col)] <- mean(col, na.rm=TRUE)
   train[,i] <- col

#feature selection
train <- changeFactors(train)
rf_selector<-randomForest(factor(y)~., train, ntrees=1000)

#choose five variables with the greatest importance rank
predictorsCols <- c("A", "B", "E", "R", "K")

#it's my weights due to unbalanced data
weights <- c(0.072625,1- 0.072625)
rf_classificator<-randomForest(factor(y)~., train[,c("y", predictorsCols)], 

testSet <- changeFactorsTest(testSet, train)
testSet <- testSet[, colnames(train)]

testSet <- rbind(train[1,-1] , testSet)
testSet <- testSet[-1,]

#here is the problem: NA returns as predicted value in some cases
predict(rf_classificator,testSet[,-1], type="prob")

#------------- additional functions --------------

getmode <- function(v) {
   v <- v[!is.na(v)]
   uniqv <- unique(v)
   uniqv[which.max(tabulate(match(v, uniqv)))]

#because randomForest works only with factors containing less then 53 levels 
#I choose 49 the most popular levels 
#and other levels change to one level - "other" 
   factorCols <- names(train %>% Filter(f = is.factor))
   for(i in 1:length(factorCols)){
     fCol <- factorCols[i];
     if(length(levels(train[,fCol])) > 50){
        subTrainSet <- subset(train, select=c("y", fCol))
        names(subTrainSet) <- c("y", "fCol");
        result <- subTrainSet %>% group_by(fCol) %>% summarise("count" = 
     n()) %>% arrange(desc(count)) 

    factorsToReplace <- result %>% slice(50:nrow(result)) %>% select(fCol) %>% as.data.frame()
    factorsToReplace <- paste(factorsToReplace$fCol)

    #replace the least popular levels to one common new level
    train[, fCol] <- as.character(train[, fCol])
    train[train[, fCol] %in% factorsToReplace, fCol] <- newFactorName
    train[, fCol] <- as.factor(train[, fCol])

#function performed on test test to unificate factors levels of test set to 
#be equal to train set
  factorCols <- names(testSet %>% Filter(f = is.factor))
  newFactorName <- "other";
  for(i in 1:length(factorCols)){
     fCol <- factorCols[i];
     if(length(levels(testSet[,fCol])) > 50){
       testSet[, fCol] <- as.character( testSet[, fCol])
       testSet[!(testSet[,fCol] %in% unique(trainSet[,fCol])), fCol] <- 
       testSet[, fCol]<- as.factor(testSet[, fCol])
  • 1
    $\begingroup$ If you know your code is horrible, wouldn't it be polite to clean it up before asking someone else to look at it? $\endgroup$ – Stephen Rauch Nov 6 '17 at 0:37
  • 3
    $\begingroup$ I cleaned it as much as I can (add comments and separate logic parts). But I understand that the quality is still not perfect $\endgroup$ – Ant Nov 6 '17 at 0:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.