R中的中心变量会阻止预测吗?

时间:2016-04-28 20:54:29

标签: r

我最近发生了一个脱毛事件,经过多次痛苦,我发现在变量上使用scale()函数阻止了我使用predict函数。我非常惊讶的是,像变量居中这样简单的东西会从根本上改变它的类型。我不擅长解释这个,所以通过运行下面的代码可能更容易看出我的意思。

df = data.frame(
  a=runif(100,45,90),
  b=runif(100,0,60),
  y=runif(100,-30,60)
)

df$a.center=scale(df$a,scale=FALSE)
df$b.center=scale(df$b,scale=FALSE)

m<-lm(y ~ a.center + b.center, data=df)

predict_df = data.frame(
  a.center=c(-10,10),
  b.center=c(-5,5)
)
predict_df$predicted = predict(m,predict_df)

我收到错误:

Error: variables ‘a.center’, ‘b.center’ were specified with different types from the fit

与此代码相比,它不使用居中变量并按预期工作:

m2<-lm(y ~ a + b, data=df)
predict_df2 = data.frame(
  a=c(-10,10),
  b=c(-5,5)
)
predict_df2$predicted = predict(m2,predict_df2)

我还注意到,在执行str(df)时,居中的变量在它们下面有一个叫“attr”的东西:

'data.frame':   100 obs. of  5 variables:
$ a       : num  71.4 57.1 83.9 49 65 ...
$ b       : num  54.56 16.76 52.43 34.11 2.43 ...
$ y       : num  -14.1 -20.8 31.3 -23 51.1 ...
$ a.center: num [1:100, 1] 2.51 -11.77 14.96 -19.89 -3.87 ...
..- attr(*, "scaled:center")= num 68.9
$ b.center: num [1:100, 1] 23.31 -14.49 21.18 2.86 -28.82 ...
..- attr(*, "scaled:center")= num 31.3

所以我的问题是:这里到底发生了什么?我应该避免使用scale功能吗?有没有一个简单的解决方法,我在str(df)看到的“attr”是什么?

2 个答案:

答案 0 :(得分:4)

查看数据框每列的类,您将看到问题:

> sapply(df, class)
        a         b         y  a.center  b.center 
"numeric" "numeric" "numeric"  "matrix"  "matrix" 

似乎scale返回一个矩阵,显然数据框很乐意将单列矩阵接受到其中一列,但lm不考虑单列矩阵相当于一个向量。所以这是3个边缘情况之间的一种奇怪和不幸的相互作用。要解决此问题,请避免使用scale

df$a.center <- df$a - mean(df$a)
df$b.center <- df$b - mean(df$b)

或者显式地将结果转换回矢量:

df$a.center <- as.vector(scale(df$a,scale=FALSE))
df$b.center <- as.vector(scale(df$b,scale=FALSE))

或者,您可以使用二维矩阵索引表示法将结果矩阵从scale分配回数据框的列中,这样做是正确的:

df[,c("a.center", "b.center")] <- scale(df[,c("a", "b")], scale=FALSE)

之后你应该看到这个:

> sapply(df, class)
        a         b         y  a.center  b.center 
"numeric" "numeric" "numeric" "numeric" "numeric" 

您对predict的来电将会成功。

答案 1 :(得分:2)

我会继续使用scale,它会为你提供以下结构化数据框(包括两个由居中生成的矩阵,晕图提到这个)

'data.frame':   100 obs. of  5 variables:
$ a       : num  86.1 76.1 75.3 55.3 53.1 ...
$ b       : num  48.99 5.99 11.34 56.47 12.9 ...
$ y       : num  -20.65 8.21 -21.6 13.36 -27.32 ...
$ a.center: num [1:100, 1] 17.85 7.87 7.11 -12.93 -15.16 ...
 ..- attr(*, "scaled:center")= num 68.2
$ b.center: num [1:100, 1] 19.6 -23.4 -18 27.1 -16.5 ...
 ..- attr(*, "scaled:center")= num 29.4

使用as.vector转换是可行的方法。只需在缩放后将它们转换回来。

只有新进程

df$a.center<-as.vector(df$a.center)
df$b.center<-as.vector(df$a.center)

然后您的结果数据再次出现在您希望的结构中:

 str(df)
'data.frame':   100 obs. of  5 variables:
 $ a       : num  86.1 76.1 75.3 55.3 53.1 ...
 $ b       : num  48.99 5.99 11.34 56.47 12.9 ...
 $ y       : num  -20.65 8.21 -21.6 13.36 -27.32 ...
 $ a.center: num  17.85 7.87 7.11 -12.93 -15.16 ...
 $ b.center: num  17.85 7.87 7.11 -12.93 -15.16 ...

然后照常运行您的线性模型和预测,取自上面的代码,结果如下:

 predict_df
 a.center b.center predicted
 1      -10       -5  9.534243
 2       10        5 16.399051

如果您愿意在插图中列出的每种方法(TRUE,FALSE和数字矢量)之间进行选择,并且知道如何正确选择特定模型所需的内容,我肯定会继续使用缩放。

我建议的原因正是因为 attr。

attr是矩阵的一个属性,它通过在矢量或帧上运行缩放返回。它是一种保存转换信息而不将其包含在实际数据框中的方法。它有点像关于转换数据的元数据。

在这种情况下,属性是删除NA值后列的平均值,它是用于居中数据的值。您可以通过如下平均计算来验证这一点:

mean(df$a)
[1] 68.23281

mean(df$b)
[1] 29.38355    

如果您还选择了缩放比例,则每个都会有第二个值,即删除NA值后列的标准偏差。

R已经为您记录了居中和缩放值。

根据您使用预测的方式以及您的工作所经历的审查,获得这些值非常有用。此外,平均值和标准偏差是一个很好的快速检查,以确定您是否在建模之前正确准备数据。

绝对值得转换为矢量或数据框的麻烦!

如果您自己尝试,请确保设置种子,以便重复转换而不会丢失值。

考虑在使用as.vector之前重命名数据框,这样您就可以保留原始文件中的属性以备将来使用,并在转换后的集合上运行线性模型。