2016-04-28 51 views
3

我最近發生了一次頭髮扯裂事件,經過很多痛苦後,我發現在變量上使用scale()函數阻止了我使用函數predict。我非常驚訝地發現,將一個變量集中在一起就會從根本上改變它的類型。我並不擅長解釋這一點,所以通過運行下面的代碼可能更容易看出我的意思。R中的中心變量會阻止預測嗎?

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

我會繼續使用規模,這爲您提供了以下結構化的數據幀(其中包括由中心產生的兩個矩陣,小品文提到了這一點)

'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是通過在矢量或幀上運行比例返回的矩陣的屬性。這是一種在實際數據框架中保存有關轉換的信息而不包含它的方法。它有點像關於轉換數據的元數據。

在這種情況下,屬性是列的平均值,在NA值被移除後,它是用於居中數據的值。你可以做一個平均值計算如下驗證這一點:

mean(df$a) 
[1] 68.23281 

mean(df$b) 
[1] 29.38355  

如果你也選擇了向規模化,就不會有每個第二值,列的NA值後的標準偏差被刪除。

R很好地記錄了您的定心和縮放值。

根據您使用預測的方式以及您的工作經過的審查,獲取這些值很有用。此外,平均值和標準偏差是一個很好的快速檢查,以查看在建模之前是否正確準備了數據。

絕對值得轉換爲矢量或數據幀的麻煩!

如果您自己嘗試此操作,請確保設置種子,以便重複轉換而不會丟失值。

並且考慮在使用as.vector之前重命名數據幀,以便您可以保留具有該屬性的原件供將來使用,並在轉換後的集合上運行線性模型。

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) 

後,你應該看到:使用2-d矩陣索引符號,它做正確的事框架

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

和您致電predict將成功。