我有一个名为data
的数据集,它有481 092行。
我将data
分成两半:
train
,用于glm()
; test
,应该用于验证模型; 然后我开始回归:
testreg <- glm(train$returnShipment ~ train$size + train$color + train$price +
train$manufacturerID + train$salutation + train$state +
train$age + train$deliverytime,
family=binomial(link="logit"), data=train)
现在的预测:
prediction <- predict.glm(testreg, newdata=test, type="response")
给我一个错误:
Error in model.frame.default(Terms, newdata, na.action=na.action, xlev=object$xlevels):
Factor 'train$manufacturerID' has new levels 125, 136, 137
现在我知道回归中省略了这些级别,因为它没有显示这些级别的任何系数。
我试过这个:predict.lm() with an unknown factor level in test data。但它在某种程度上对我不起作用,或者我可能只是没有得到如何实现它。我想预测相关的二进制变量,但当然只能预测现有的系数。上面的链接建议告诉R,具有新级别的行应该被称为/或被视为NA。
我该怎么办?
Z. Li编辑建议的方法
我在第一步遇到了问题:
xlevels <- testreg$xlevels$manufacturerID
mID125 <- xlevels[1]
但mID125
是NULL
!我做错了什么?
答案 0 :(得分:4)
在固定效应建模中,包括线性模型和广义线性模型,无法估计新因子水平。 glm
(以及lm
)会记录在模型拟合期间显示和使用的因子级别,并且可以在testreg$xlevels
中找到。
您的模型估算模型公式为:
returnShipment ~ size + color + price + manufacturerID + salutation +
state + age + deliverytime
然后predict
抱怨manufactureID
的新因子级别125,136,137。这意味着,这些级别不在testreg$xlevels$manufactureID
内,因此没有相关的预测系数。在这种情况下,我们必须删除此因子变量并使用预测公式:
returnShipment ~ size + color + price + salutation +
state + age + deliverytime
但是,标准predict
例程无法采用您的自定义预测公式。通常有两种解决方案:
testreg
提取模型矩阵和模型系数,并通过矩阵向量乘法手动预测我们想要的模型项。这是你帖子中提到的the link建议做的事情; test
中的因子级别重置为testreg$xlevels$manufactureID
中出现的任何一个级别,例如testreg$xlevels$manufactureID[1]
。因此,我们仍然可以使用标准predict
进行预测。现在,让我们首先选择用于模型拟合的因子水平
xlevels <- testreg$xlevels$manufacturerID
mID125 <- xlevels[1]
然后我们将此级别分配给您的预测数据:
replacement <- factor(rep(mID125, length = nrow(test)), levels = xlevels)
test$manufacturerID <- replacement
我们准备预测:
pred <- predict(testreg, test, type = "link") ## don't use type = "response" here!!
最后,我们通过减去因子估计值来调整此线性预测值:
est <- coef(testreg)[paste0(manufacturerID, mID125)]
pred <- pred - est
最后,如果您想要对原始比例进行预测,则应用链接函数的反转:
testreg$family$linkinv(pred)
<强>更新强>
您抱怨在尝试上述解决方案时遇到了各种麻烦。这就是原因。
您的代码:
testreg <- glm(train$returnShipment~ train$size + train$color +
train$price + train$manufacturerID + train$salutation +
train$state + train$age + train$deliverytime,
family=binomial(link="logit"), data=train)
是指定模型公式的一种非常糟糕的方法。 train$returnShipment
等会严格限制将变量置于数据框train
的环境,并且您将在稍后使用其他数据集进行预测时遇到问题,例如test
。强>
作为这种缺点的简单示例,我们模拟一些玩具数据并适合GLM:
set.seed(0); y <- rnorm(50, 0, 1)
set.seed(0); a <- sample(letters[1:4], 50, replace = TRUE)
foo <- data.frame(y = y, a = factor(a))
toy <- glm(foo$y ~ foo$a, data = foo) ## bad style
> toy$formula
foo$y ~ foo$a
> toy$xlevels
$`foo$a`
[1] "a" "b" "c" "d"
现在,我们看到所有内容都带有前缀foo$
。在预测期间:
newdata <- foo[1:2, ] ## take first 2 rows of "foo" as "newdata"
rm(foo) ## remove "foo" from R session
predict(toy, newdata)
我们收到错误:
eval(expr,envir,enclos)中的错误:object&#39; foo&#39;找不到
好的方式是指定从函数的data
参数获取数据的环境:
foo <- data.frame(y = y, a = factor(a))
toy <- glm(y ~ a, data = foo)
然后foo$
消失。
> toy$formula
y ~ a
> toy$xlevels
$a
[1] "a" "b" "c" "d"
这可以解释两件事:
testreg$xlevels$manufactureID
时,您会获得NULL
; 您发布的预测错误
Error in model.frame.default(Terms, newdata, na.action=na.action, xlev=object$xlevels):
Factor 'train$manufacturerID' has new levels 125, 136, 137
抱怨train$manufacturerID
而不是test$manufacturerID
。
答案 1 :(得分:3)
由于您已根据rownumbers对train
和test
样本进行了划分,因此您的变量的某些因子级别在列车和测试样本中均未得到相同的表示。
您需要进行分层抽样,以确保列车和测试样本都具有所有因子水平表示。使用stratified
包中的splitstackshape
。