2017-05-14 52 views
1

我有一個數據集,我分成訓練和測試子集中的方式如下:避免失敗時的一個因素在測試新的水平設置

train_ind <- sample(seq_len(nrow(dataset)), size=(2/3)*nrow(dataset)) 
train <- dataset[train_ind] 
test <- dataset[-train_ind] 

然後,我用它來訓練GLM:

glm.res <- glm(response ~ ., data=dataset, subset=train_ind, family = binomial(link=logit)) 

最後,我用它來預測在我的測試集:

preds <- predict(glm.res, test, type="response") 

根據樣品,這個失敗,錯誤:

Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) : factor has new levels

請注意,該值顯示在整個數據集上,但顯然不在訓練集上。我想要做的是使預測功能忽略這些新的因素。即使它已經對這些因素進行了二值化,但我不明白爲什麼它可以假設新值(因此,不是線性模型中的變量)僅僅爲0,這會產生正確的行爲。

有沒有辦法做到這一點?

回答

1

予先從以下數據生成處理(二元響應的變量,一個數值獨立變量和3個分類自變量):

set.seed(1) 
n <- 500 
y <- factor(rbinom(n, size=1, p=0.7)) 
x1 <- rnorm(n) 
x2 <- cut(runif(n), breaks=seq(0,1,0.2)) 
x3 <- cut(runif(n), breaks=seq(0,1,0.25)) 
x4 <- cut(runif(n), breaks=seq(0,1,0.1)) 
df <- data.frame(y, x1, x2, x3, x4) 

在這裏,我建立訓練並在某種程度上檢測設置爲具有一些分類協變量(x2和)在測試組與多個類別比在訓練集:

idx <- which(df$x2!="(0.6,0.8]" & df$x3!="(0,0.25]") 
train_ind <- sample(idx, size=(2/3)*length(idx)) 
train <- df[train_ind,] 
train$x2 <- droplevels(train$x2) 
train$x3 <- droplevels(train$x3) 
test <- df[-train_ind,] 

table(train$x2) 
(0,0.2] (0.2,0.4] (0.4,0.6] (0.8,1] 
    55  40  53  49 

table(test$x2) 
(0,0.2] (0.2,0.4] (0.4,0.6] (0.6,0.8] (0.8,1] 
    58  48  45  90  62 

table(train$x3) 
(0.25,0.5] (0.5,0.75] (0.75,1] 
     66   61   70 

table(test$x3) 
(0,0.25] (0.25,0.5] (0.5,0.75] (0.75,1] 
    131   63   47   62 

當然,predict產生消息錯誤即d通過@ Setzer22上述旁切:

glm.res <- glm(y ~ ., data=train, family = binomial(link=logit)) 
preds <- predict(glm.res, test, type="response") 

Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) : factor x2 has new levels (0.6,0.8]

這是一個(不優雅)的方式來刪除的train行本身擁有的協新的水平:

dropcats <- function(k) { 
    xtst <- test[,k] 
    xtrn <- train[,k] 
    cmp.tst.trn <- (unique(xtst) %in% unique(xtrn)) 
    if (is.factor(xtst) & any(!cmp.tst.trn)) { 
     cat.tst <- unique(xtst) 
     apply(test[,k]==matrix(rep(cat.tst[cmp.tst.trn],each=nrow(test)), 
         nrow=nrow(test)),1,any) 
    } else { 
     rep(TRUE,nrow(test)) 
    } 
} 
filt <- apply(sapply(2:ncol(df),dropcats),1,all) 
subset.test <- test[filt,] 

在的子集subset.test測試集x2和沒有新類別:

table(subset.test[,"x2"]) 
    (0,0.2] (0.2,0.4] (0.4,0.6] (0.6,0.8] (0.8,1] 
     26  25  20   0  28 

table(subset.test[,"x3"]) 
    (0,0.25] (0.25,0.5] (0.5,0.75] (0.75,1] 
     0   29   29   41 

現在predict很好地工作:

preds <- predict(glm.res, subset(test,filt), type="response") 
head(preds) 

     30  39  41  49  55  56 
0.7732564 0.8361226 0.7576259 0.5589563 0.8965357 0.8058025 

希望這可以幫助你。

+0

感謝您的回答!我發現在R中似乎沒有簡單的方法來做到這一點,我感到很沮喪。在我看來,這似乎是一個基本的邊緣情況,實現應該覆蓋,解決方案很簡單。有沒有我沒有考慮到的事情?爲什麼它不能忽略任何新的價值? – Setzer22

相關問題