【问题标题】:"Factor has new levels" error for variable I'm not using我没有使用的变量的“因子有新的水平”错误
【发布时间】:2014-04-14 10:55:17
【问题描述】:

考虑一个简单的数据集,分成训练集和测试集:

dat <- data.frame(x=1:5, y=c("a", "b", "c", "d", "e"), z=c(0, 0, 1, 0, 1))
train <- dat[1:4,]
train
#   x y z
# 1 1 a 0
# 2 2 b 0
# 3 3 c 1
# 4 4 d 0
test <- dat[5,]
test
#   x y z
# 5 5 e 1

当我训练一个逻辑回归模型以使用 x 预测 z 并获得测试集预测时,一切都很好:

mod <- glm(z~x, data=train, family="binomial")
predict(mod, newdata=test, type="response")
#         5 
# 0.5546394 

但是,这在具有“因子具有新水平”错误的等效逻辑回归模型上失败:

mod2 <- glm(z~.-y, data=train, family="binomial")
predict(mod2, newdata=test, type="response")
# Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) : 
#   factor y has new level e

自从我从我的模型方程中删除了y,我很惊讶地看到这个错误消息。在我的应用程序中,dat 很宽,所以z~.-y 是最方便的模型规范。我能想到的最简单的解决方法是从我的数据框中删除 y 变量,然后使用 z~. 语法训练模型,但我希望有一种方法可以使用原始数据集而无需删除列。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以尝试在模型对象中更新mod2$xlevels[["y"]]

    mod2 <- glm(z~.-y, data=train, family="binomial")
    mod2$xlevels[["y"]] <- union(mod2$xlevels[["y"]], levels(test$y))
    
    predict(mod2, newdata=test, type="response")
    #        5 
    #0.5546394 
    

    另一种选择是从训练数据中排除(但不删除)“y”

    mod2 <- glm(z~., data=train[,!colnames(train) %in% c("y")], family="binomial")
    predict(mod2, newdata=test, type="response")
    #        5 
    #0.5546394 
    

    【讨论】:

    • 这些都是不错的选择——谢谢!帖子中描述的行为几乎看起来像一个错误(我不明白为什么我必须使用第二个模型规范从我的数据框中删除 y),但这些都是明智的解决方法。
    • 如果您在glm 上运行debug,您可以看到它在哪里创建模型项mt &lt;- attr(mf, "terms")。我认为y 被视为在模型中,因为当您使用z~.-y 时,公式扩展为z ~ (x + y) - y,所以y 在技术上在模型中,但我没有任何其他见解(只是解决方法:))
    【解决方案2】:

    我对这个问题困惑了很长时间。但是,有一个简单的解决方案。其中一个变量“交通类型”有 20 个因素,而对于一个因素,即 17,只有一行。因此,这一行可能出现在训练数据或测试数据中。在我的情况下,它存在于测试数据中,因此出现错误 - 因素“交通类型”的新级别为 17,因为火车数据中没有级别为 17 的行。我从数据集中删除了这一行,模型运行得很好

    【讨论】:

    • 嗨 Bhavna -- 是的,如果测试集对于您在模型中使用的因子有一个新的水平,那么您肯定会收到此错误,并且删除该观察是一种合理的继续方式。在这个问题中,我特别询问了一个我在模型中没有使用但恰好出现在我的数据框中的因素。在这种情况下,我们不必从测试集中删除观察结果,matt_k 提供了一些不错的方法。
    【解决方案3】:

    我们可以概括@matt_k 的伟大的solution 以将其应用于高维数据,其中training 和@ 中有多个不同级别的因素987654323@套,像这样:

    dat2
    #   x y1 y2 z
    # 1 1  a  A 0
    # 2 2  b  B 0
    # 3 3  c  C 1
    # 4 4  d  D 0
    # 5 5  e  E 1
    

    当我们像以前一样分为测试和训练时,

    train <- dat2[1:4, ]
    test <- dat2[5, ]
    

    y1y2 test 的级别将与 train 的级别不同,我们会收到错误消息。

    mod <- glm(z ~ ., data=train, family="binomial")
    predict(mod, newdata=test, type="response")
    # Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) : 
    #   factor y1 has new level e
    

    对于高维数据,纠正每一个失败的因素是相当无聊的,所以我们可能想要循环它们。

    要么,坏人属于"factor" 类,要么属于"character" 类(在我们的例子中)。由于这些将包含在“xlevels”中,因此我们使用一个小助手来识别它们,

    is.prone <- function(x) is.factor(x) | is.character(x)
    

    并将其放入Map

    id <- sapply(dat2, is.prone)
    mod$xlevels <- Map(union, mod$xlevels, lapply(dat2[id], unique))
    

    那么它应该可以工作了。

    predict(mod, newdata=test, type="response")
    #            5 
    # 5.826215e-11 
    # Warning message:
    # In predict.lm(object, newdata, se.fit, scale = 1, type = if (type ==  :
    #   prediction from a rank-deficient fit may be misleading
    

    dat2 <- structure(list(x = 1:5, y1 = c("a", "b", "c", "d", "e"), y2 = c("a", 
    "b", "c", "d", "e"), z = c(0, 0, 1, 0, 1)), class = "data.frame", row.names = c(NA, 
    -5L))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-07
      • 1970-01-01
      • 2021-02-22
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      • 2017-05-23
      相关资源
      最近更新 更多