Predict() - 或许我没有理解它

69

我今天早些时候发布了一个问题,关于使用predict函数时出现的错误。我已经纠正了这个错误,并且认为我走在了正确的道路上。

我有许多观测值(实际值),并且我想要推断或预测一些数据点。我使用lm创建了一个模型,然后尝试使用实际值作为预测输入来使用predict

这段代码和我的先前帖子中重复,但是在这里:

df <- read.table(text = '
     Quarter Coupon      Total
1   "Dec 06"  25027.072  132450574
2   "Dec 07"  76386.820  194154767
3   "Dec 08"  79622.147  221571135
4   "Dec 09"  74114.416  205880072
5   "Dec 10"  70993.058  188666980
6   "Jun 06"  12048.162  139137919
7   "Jun 07"  46889.369  165276325
8   "Jun 08"  84732.537  207074374
9   "Jun 09"  83240.084  221945162
10  "Jun 10"  81970.143  236954249
11  "Mar 06"   3451.248  116811392
12  "Mar 07"  34201.197  155190418
13  "Mar 08"  73232.900  212492488
14  "Mar 09"  70644.948  203663201
15  "Mar 10"  72314.945  203427892
16  "Mar 11"  88708.663  214061240
17  "Sep 06"  15027.252  121285335
18  "Sep 07"  60228.793  195428991
19  "Sep 08"  85507.062  257651399
20  "Sep 09"  77763.365  215048147
21  "Sep 10"  62259.691  168862119', header=TRUE)

str(df)
'data.frame':   21 obs. of  3 variables:
 $ Quarter   : Factor w/ 24 levels "Dec 06","Dec 07",..: 1 2 3 4 5 7 8 9 10 11 ...
 $ Coupon: num  25027 76387 79622 74114 70993 ...
 $ Total: num  132450574 194154767 221571135 205880072 188666980 ...

代码:

model <- lm(df$Total ~ df$Coupon, data=df)

> model

Call:
lm(formula = df$Total ~ df$Coupon)

Coefficients:
(Intercept)    df$Coupon  
  107286259         1349 

预测代码(基于以前的帮助):

(这些是我想要使用的预测器值,以获得预测值)

Quarter = c("Jun 11", "Sep 11", "Dec 11")
Total = c(79037022, 83100656, 104299800)
Coupon = data.frame(Quarter, Total)

Coupon$estimate <- predict(model, newdate = Coupon$Total)

现在,当我运行它时,我收到以下错误消息:

Error in `$<-.data.frame`(`*tmp*`, "estimate", value = c(60980.3823396919,  : 
  replacement has 21 rows, data has 3

我用来构建模型的原始数据框中有21个观察值。现在我正在尝试基于该模型预测3个值。

要么是我真的不理解这个函数,要么我的代码出错了。

希望能得到帮助。

谢谢


3
为使这个工作正常运转,您几乎肯定需要使用 lm 函数的 data 参数,即 model <- lm(Total ~ Coupon, data=df)。然后建议您使用 Coupon$estimate <- predict(model, newdata = Coupon)$Total - Ben Bolker
2
@BenBolker 我同意第一部分,但对于第二部分不太确定。我认为 predict(model, newdata = Coupon) 应该是他想要的。 - joran
1
@joran 是的,我认为你是对的。 - Ben Bolker
@BenBolker和@joran更新了代码以反映Ben建议的data=df。相同的结果。然后我更新了joran的建议。相同的错误。 - mikebmassey
你没有按照Ben的指示进行更新。注意到你的公式规范有什么不同了吗?df$TotalTotal之间的区别。按照你的方式,当你使用predict时,它会寻找一个名为df$Coupon的变量,而不是只有Coupon(我想)。至少,这些名称不匹配。 - joran
@mikebmassey -- 还有,再看一下我对你问题的回答。我的第一个答案给出了错误的信息,但几个小时前已经更新了。我认为现在的答案非常好,并且根据?predict.lm的建议提出了额外的建议,即newdata应该是一个包含Coupon或任何其他预测变量的数据框。抱歉--我以为SO会自动通知您我的答案和评论的更改。 - Josh O'Brien
4个回答

106

首先,你想要使用

model <- lm(Total ~ Coupon, data=df)

不是 model <-lm(df$Total ~ df$Coupon, data=df)

其次,通过使用 lm(Total ~ Coupon),你正在拟合一个模型,其中以Total为响应变量,Coupon为预测变量。也就是说,你的模型的形式为 Total = a + b*Coupon,其中ab是要估计的系数。请注意,响应变量位于~的左边,而预测变量位于右边。

因此,当你要求R为模型提供预测值时,你必须提供一组新的预测变量值,即Coupon的新值,而不是Total

第三,根据你对newdata的规定,看起来你实际上是在寻找将Total作为Coupon的函数拟合的模型,而不是反过来。要做到这一点:

model <- lm(Coupon ~ Total, data=df)
new.df <- data.frame(Total=c(79037022, 83100656, 104299800))
predict(model, new.df)

我认为你的公式是反过来的。此外,new.df 应该包含 Coupon 而不是 Total。另外,我的回答也同样有效 ;) - Josh O'Brien
1
@JoshO'Brien:我正在使用OP发布的新数据,其中指定了“Total”的值。这意味着他实际上是想要一个模型来预测“Coupon”。 - Hong Ooi
但他总是把Total放在公式的左边,就像您在帖子的开头行所做的那样!除非我非常困惑,否则Coupon应该是预测因子。(这并不像您试图传达的概念那样重要)。 - Josh O'Brien
我怀疑原帖作者可能对于~符号应该放在哪一边的响应变量有些困惑。我会更新我的回答。 - Hong Ooi
谢谢大家的帮助。针对Josh的观点 - 我正在尝试预测“优惠券”,而不是“总计”,所以如果我让大家感到困惑,我很抱歉。我按照Hong的方法做了,并且确实使它工作了。谢谢。然而,当我运行predict(model, new.df)时,我仍然得到21个观察结果,而不是我试图在new.df中确定的3个结果。predict的整个目的是使用lm并预测新值,对吗?还是我对它的功能感到困惑?再次感谢。 - mikebmassey
1
@mikebmassey:请再次检查我的答案,我刚刚编辑过。确保公式的左侧有“Coupon”,并且您输入代码完全符合我在答案的最后三行中的格式。 - Hong Ooi

11
感谢Hong,那正是我遇到的问题。你得到的错误提示表明行数有误,但实际上问题在于使用了一个命令训练模型,导致参数名称错误。
这实际上是一个非常关键的细节,对于lm等模型来说完全不明显。一些教程提到执行类似lm(olive$Area@olive$Palmitic)的代码 - 最终变量名为olive$Area而不是Area,因此使用anewdata<-data.frame(Palmitic=2)创建条目后不能使用。如果使用lm(Area@Palmitic,data=olive),则变量名正确,预测有效。
真正的问题是错误消息根本没有指示问题所在:

警告信息:'anewdata'有1行,但找到X行变量


谢谢,这是一个非常重要的点,我也遇到了你提到的错误。针对Hong的回复应用你的答案:如果他的new.df中的列名不是“Total”,而是与原始数据框架相同的列名,则他将会得到你(和我)遇到的错误。因此,确保新数据中的列名与原始模型中的预测变量名称相同非常重要。 - NeonBlueHair
将其标记为“不是答案”。使用@运算符表示您正在处理S4对象,这与原始问题或答案无关。您错误地将您的困难与未指定的作业问题混淆,并将其视为已充分回答的更简单的问题。 - IRTFM

5
为了避免错误,关于新数据集的一个重要点是独立变量的名称必须与模型中报告的名称相同。另一种方法是在不创建新数据集的情况下嵌套这两个函数。
model <- lm(Coupon ~ Total, data=df)
predict(model, data.frame(Total=c(79037022, 83100656, 104299800)))

注意模型。下面两个命令很相似,但对于预测函数而言,第一个有效而第二个无效。

model <- lm(Coupon ~ Total, data=df) #Ok
model <- lm(df$Coupon ~ df$Total) #Ko

4

在预测代码中,您使用了newdate而不是newdata,请确保一次。只需使用Coupon$estimate <- predict(model, Coupon)它会起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接