nrow(subs-6ren">
gpt4 book ai didi

r - 如何调试线性模型和预测的 "factor has new levels"错误

转载 作者:行者123 更新时间:2023-12-01 07:00:10 24 4
gpt4 key购买 nike

我正在尝试制作和测试一个线性模型,如下所示:

lm_model <- lm(Purchase ~., data = train)
lm_prediction <- predict(lm_model, test)

这会导致以下错误,说明 Product_Category_1列的值存在于 test 中数据框但不是 train数据框):

factor Product_Category_1 has new levels 7, 9, 14, 16, 17, 18



但是,如果我检查这些,它们肯定会出现在两个数据框中:
> nrow(subset(train, Product_Category_1 == "7"))
[1] 2923
> nrow(subset(test, Product_Category_1 == "7"))
[1] 745
> nrow(subset(train, Product_Category_1 == "9"))
[1] 312
> nrow(subset(test, Product_Category_1 == "9"))
[1] 92

还显示了 train 的表格和 test表明它们具有相同的因素:
> table(train$Product_Category_1)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
110820 18818 15820 9265 118955 16159 2923 89511 312 4030 19113 3108 4407 1201 4991 7730 467 2430
> table(test$Product_Category_1)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
27533 4681 4029 2301 29637 4005 745 22621 92 1002 4847 767 1033 299 1212 1967 100 645
>

最佳答案

目录:

  • 演练的简单示例
  • 给用户的建议
  • 我们可以从拟合模型对象中获得的有用信息
  • 好的,我现在知道问题所在了,但是如何制作 predict工作?
  • 有没有更好的方法来避免此类问题?


  • 演练的简单示例

    这是一个足够简单的可重复示例来提示您发生了什么。
    train <- data.frame(y = runif(4), x = c(runif(3), NA), f = factor(letters[1:4]))
    test <- data.frame(y = runif(4), x = runif(4), f = factor(letters[1:4]))
    fit <- lm(y ~ x + f, data = train)
    predict(fit, newdata = test)
    #Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) :
    # factor f has new levels d

    我正在拟合一个参数多于数据的模型,因此该模型是秩亏的(最后解释)。不过这并不影响 lmpredict工作。

    如果你只是检查 table(train$f)table(test$f)它没有用,因为问题不是由变量 f 引起的但来自 NAx . lmglm删除不完整的案例,即至少有一个 NA 的行(参见 ? complete.cases )进行模型拟合。他们必须这样做,否则用于 QR 分解的底层 FORTRAN 例程将失败,因为它无法处理 NA .如果您查看 ?lm 处的文档你会看到这个函数有一个参数 na.action默认为 na.omit .您也可以将其设置为 na.exclude但是 na.pass其中保留 NA会导致 FORTRAN 错误:
    fit <- lm(y ~ x + f, data = train, na.action = na.pass)
    #Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) :
    # NA/NaN/Inf in 'x'

    让我们删除 NA来自训练数据集。
    train <- na.omit(train)
    train$f
    #[1] a b c
    #Levels: a b c d
    f现在有一个未使用的级别 "d" . lmglm将在构建模型框架(以及后来的模型矩阵)时删除未使用的级别:
    ## source code of lm; don't run
    mf$drop.unused.levels <- TRUE
    mf[[1L]] <- quote(stats::model.frame)
    mf <- eval(mf, parent.frame())

    这不是用户可控的。原因是如果包含未使用的级别,它将在模型矩阵中生成一列零。
    mf <- model.frame(y ~ x + f, data = train, drop.unused.levels = FALSE)
    model.matrix(y ~ x + f, data = mf)
    # (Intercept) x fb fc fd
    #1 1 0.90021178 0 0 0
    #2 1 0.10188534 1 0 0
    #3 1 0.05881954 0 1 0
    #attr(,"assign")
    #[1] 0 1 2 2 2
    #attr(,"contrasts")
    #attr(,"contrasts")$f
    #[1] "contr.treatment"

    这是不受欢迎的,因为它会产生 NA虚拟变量系数 fd .来自 drop.unused.levels = TRUElm 强制和 glm :
    mf <- model.frame(y ~ x + f, data = train, drop.unused.levels = TRUE)
    model.matrix(y ~ x + f, data = mf)
    # (Intercept) x fb fc
    #1 1 0.90021178 0 0
    #2 1 0.10188534 1 0
    #3 1 0.05881954 0 1
    #attr(,"assign")
    #[1] 0 1 2 2
    #attr(,"contrasts")
    #attr(,"contrasts")$f
    #[1] "contr.treatment"
    fd消失了,并且
    mf$f
    #[1] a b c
    #Levels: a b c

    现在不存在的 "d"级别将导致 predict 中的“新因子级别”错误.

    给用户的建议

    强烈建议所有用户在拟合模型时手动执行以下操作:
  • [不。 1] 删除不完整的案例;
  • [不。 2] 删除未使用的因子水平。

  • 这正是这里推荐的程序: How to debug "contrasts can be applied only to factors with 2 or more levels" error?这让用户知道什么 lmglm在幕后做,使他们的调试生活更容易。

    请注意,列表中应该还有另一个建议:
  • [不。 0] 做自己的子集

  • 用户可能偶尔会使用 subset争论。但是有一个潜在的陷阱:并非所有因子水平都可能出现在子集数据集中,因此在使用 predict 时您可能会得到“新的因子水平”。之后。

    当您编写包装 lm 的函数时,上述建议尤为重要。或 glm .您希望您的功能健壮。要求您的函数返回信息性错误而不是等待 lmglm提示。

    我们可以从拟合模型对象中获得的有用信息
    lmglm返回 xlevels拟合对象中的值。它包含因子水平 实际上用于模型拟合。
    fit$xlevels
    #$f
    #[1] "a" "b" "c"

    因此,如果您没有遵循上面列出的建议并且在因子水平方面遇到问题,请使用此 xlevels应该首先检查。

    如果你想使用类似 table 的东西计算每个因子水平有多少个案例,这里有一个方法: Get number of data in each factor level (as well as interaction) from a fitted lm or glm [R] ,虽然制作模型矩阵可以使用很多 RAM。

    好的,我现在知道问题所在了,但是如何制作 predict工作?

    如果您不能选择使用不同的一组 traintest数据集(请参阅下一节),您需要在 test 中设置这些因子水平但不在 xlevelsNA .然后 predict只会预测 NA对于这种不完整的情况。

    有没有更好的方法来避免此类问题?

    人们将数据拆分为 traintest因为他们想做交叉验证。第一步是申请 na.omit在你的完整数据集上去掉 NA噪音。然后我们可以对剩下的东西做一个随机分区,但是这种天真的方法可能会导致
  • test 中的一些因子水平但不在 train (哎呀,我们在使用 predict 时得到“新因子水平”错误);
  • train 中的一些因子变量删除未使用的级别后只有 1 个级别(哎呀,我们在使用 lmglm 时出现“对比”错误);

  • 因此,强烈建议您进行一些更复杂的分区,例如分层抽样。

    实际上还有另一个危害,但不会导致编程错误:
  • train 的模型矩阵是秩亏的(哎呀,我们在使用 predict 时收到“对秩亏模型的预测可能具有误导性”警告)。

  • 关于模型拟合的秩亏,见 lme4::lmer reports "fixed-effect model matrix is rank deficient", do I need a fix and how to?秩亏不会对模型估计和检查造成问题,但可能对预测造成危害: R lm , Could anyone give me an example of the misleading case on “prediction from a rank-deficient”?但是,此类问题更难避免,尤其是当您有许多因素并且可能存在交互作用时。

    关于r - 如何调试线性模型和预测的 "factor has new levels"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51552203/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com