2013-02-26 65 views
11

好吧,這是一個奇怪的。我懷疑這是data.table裏面的一個錯誤,但是如果有人能解釋爲什麼會發生這種情況 - update究竟做了什麼?爲什麼在分組的data.table中使用lm更新會丟失模型數據?

我在data.table中使用list(list())技巧來存儲擬合模型。當您爲不同的分組創建一個lm對象序列,然後創建這些模型的update時,所有模型的模型數據將變爲最後一個分組的模型數據。這似乎是一個參考掛在哪裏應該有一個副本,但我無法找到在哪裏,我不能再現lmupdate以外的此。

具體的例子:

與虹膜數據開始,首先使三種不同的樣品尺寸,則適合的lm模型以每個物種,更新這些模型:

set.seed(3) 
DT = data.table(iris) 
DT = DT[rnorm(150) < 0.9] 
fit = DT[, list(list(lm(Sepal.Length ~ Sepal.Width + Petal.Length))), 
      by = Species] 
fit2 = fit[, list(list(update(V1[[1]], ~.-Sepal.Length))), by = Species] 

的原始數據表具有不同數量的每個物種

DT[,.N, by = Species] 
#  Species N 
# 1:  setosa 41 
# 2: versicolor 39 
# 3: virginica 42 

而且第一嵌入證實thsi:

fit[, nobs(V1[[1]]), by = Species] 
#  Species V1 
# 1:  setosa 41 
# 2: versicolor 39 
# 3: virginica 42 

但更新的第二擬合出42所有型號

fit2[, nobs(V1[[1]]), by = Species] 
#  Species V1 
# 1:  setosa 42 
# 2: versicolor 42 
# 3: virginica 42 

我們也可以看看其中包含用於擬合數據的模型屬性,並看到所有該模型確實使用了最終的組數據。問題是這是怎麼發生的?

head(fit$V1[[1]]$model) 
# Sepal.Length Sepal.Width Petal.Length 
# 1   5.1   3.5   1.4 
# 2   4.9   3.0   1.4 
# 3   4.7   3.2   1.3 
# 4   4.6   3.1   1.5 
# 5   5.0   3.6   1.4 
# 6   5.4   3.9   1.7 
head(fit$V1[[3]]$model) 
# Sepal.Length Sepal.Width Petal.Length 
# 1   6.3   3.3   6.0 
# 2   5.8   2.7   5.1 
# 3   6.3   2.9   5.6 
# 4   7.6   3.0   6.6 
# 5   4.9   2.5   4.5 
# 6   7.3   2.9   6.3 
head(fit2$V1[[1]]$model) 
# Sepal.Length Sepal.Width Petal.Length 
# 1   6.3   3.3   6.0 
# 2   5.8   2.7   5.1 
# 3   6.3   2.9   5.6 
# 4   7.6   3.0   6.6 
# 5   4.9   2.5   4.5 
# 6   7.3   2.9   6.3 
head(fit2$V1[[3]]$model) 
# Sepal.Length Sepal.Width Petal.Length 
# 1   6.3   3.3   6.0 
# 2   5.8   2.7   5.1 
# 3   6.3   2.9   5.6 
# 4   7.6   3.0   6.6 
# 5   4.9   2.5   4.5 
# 6   7.3   2.9   6.3 
+1

這種行爲可以用這個簡單地重新創建:'m1 < - fit $ V1 [[2]]; m2 < - update(m1,。〜。)'; 'm1'和'm2'則不同。也許這將有助於搞清楚。 – Aaron 2013-02-26 19:37:28

+0

謝謝,我試了很長時間來簡化這一點 – Corone 2013-02-26 20:12:13

+3

你讀過http://stackoverflow.com/questions/13690184 - 它可能是相關的。 – hadley 2013-02-26 23:25:34

回答

4

這不是一個答案,但過長的評論

.Environment的條款成分是每個生成的模型相同

e1 <- attr(fit[['V1']][[1]]$terms, '.Environment') 
e2 <- attr(fit[['V1']][[2]]$terms, '.Environment') 
e3 <- attr(fit[['V1']][[3]]$terms, '.Environment') 
identical(e1,e2) 
## TRUE 
identical(e2, e3) 
## TRUE 

看來,data.table使用相同的位內存(我的非技術術語) 每組評估j(這是有效的)。但是,當調用update時,它正在使用它來重新設置模型。這將包含最後一組的值。

所以,如果你做傻事這一點,它會工作

fit = DT[, { xx <-list2env(copy(.SD)) 

      mymodel <-lm(Sepal.Length ~ Sepal.Width + Petal.Length) 
      attr(mymodel$terms, '.Environment') <- xx 
      list(list(mymodel))}, by= 'Species'] 





lfit2 <- fit[, list(list(update(V1[[1]], ~.-Sepal.Width))), by = Species] 
lfit2[,lapply(V1,nobs)] 
V1 V2 V3 
1: 41 39 42 
# using your exact diagnostic coding. 
lfit2[,nobs(V1[[1]]),by = Species] 
     Species V1 
1:  setosa 41 
2: versicolor 39 
3: virginica 42 

不是一個長期的解決方案,但至少一種變通方法。

相關問題