R 从多元多项式模型预测

R predicting from multivariate polynomial models

我在数据框(数据)中有 3 列数据,没有 headers。

第一列和第二列是自变量,第三列是因变量。

我必须在自变量中拟合一个 3 阶多项式。

我做到了:

dm <- data.matrix(data[,1:2])
pmodel <- lm(data.matrix(data[,3])~poly(dm,degree = 3,raw=TRUE))

现在我如何预测给定的一对自变量的答案,例如 (0.77,0.36)?

我试过了:

predict.lm(pmodel,data.frame(0.77,0.36))

但这给出了一些错误提示:

'newdata' 有 1 行,但找到的变量有 100 行

OK,有几个问题要处理。我首先尝试模仿您描述的情况,一个没有名字的数据集。事实上,如果它是一个 data.frame 对象(即 class(data) returns data.frame),它几乎肯定有名字。如果您只是 运行 创建新数据的位 data.frame:

就可以看到这一点
data.frame(0.77,0.36)

自动名称很难看,但它们就在那里:X0.77 X0.36

但是让我们获取没有名称的数据,看看会发生什么。

 ## make a matrix without names from iris data
 data <- matrix(unlist(iris[,1:3]),nrow=nrow(iris))

 pmodel <- lm(data[,3]~poly(data[,1:2],degree = 3,raw=TRUE))
 # variable names are ugly
 summary(pmodel)

不使用名称的困难在于 predict() 无法弄清楚如何将新值映射到数据中的列,除非您传递给 newdata 参数的 data.frame 中的标签与某些内容匹配在模型框架中。所以在下面的代码中你会得到一个警告,因为新数据没有正确的名称,也没有正确的长度。

 test <- predict.lm(pmodel,data.frame(0.77,0.36))

但是测试里面有东西?

 all.equal(test,fitted(pmodel)) # TRUE

发生的事情是 predict() 忽略了新数据,只返回了模型的拟合值。那么,使用带名称的 data.frame 怎么样?

 df = as.data.frame(data) 
 names(df) #  automatically creates variable names
 names(df) <- c("X","Y","Z") # change 'em if you want

 pmodel2 <- lm(Z~poly(X,Y,degree=3, raw=TRUE),data=df)

我们可以检查这是否与之前的对象相同:

 all.equal(coef(pmodel),coef(pmodel2)) # matches except for names

但是,如果我们再次尝试预测,我们会得到一个不同的错误!

 nd <- data.frame(X=0.77,Y=0.36)
 predict(pmodel2,newdata=nd)

Error in colnames<-(*tmp*, value = apply(z, 1L, function(x) paste(x, : attempt to set 'colnames' on an object with less than two dimensions

出于我无法理解但与多项式计算方式相关的原因,您至少需要 2 行新数据。

 nd <- data.frame(X=c(0.77,0.89),Y=c(0.36,0.4))
 predict(pmodel2,newdata=nd)

 # check against fitted values
 predict(pmodel2,newdata=df[1:2,])
 fitted(pmodel2)[1:2]

如果你真的只需要一个预测,你可以复制它并丢弃结果的一行。

nd <- data.frame(X=rep(0.77,times=2),Y=rep(0.36,times=2))
predict(pmodel2,newdata=nd)[1]

编辑:问题是列数未知,因此很难自动使用 poly() 中的列名。但!我们可以用名字做计算。像这样创建公式

 ff <- as.formula(paste("Z~poly(",
                  paste0(names(df)[1:2],collapse=", "),
                  ", degree=3,raw=TRUE)"))

然后是

  pmodel <- lm(ff, data=df)

可能有更好的方法来做到这一点,但这很有效。