12

わかりました、これは奇妙なものです。これは内部のバグdata.tableだと思いますが、なぜこれが起こっているのかを誰かが説明できれば便利です-update正確には何をしているのですか?

フィットしたモデルを保存するためにlist(list())内部のトリックを使用しています。異なるグループごとdata.tableにオブジェクトのシーケンスを作成し、次にそれらのモデルを作成すると、すべてのモデルのモデルデータが最後のグループのモデルデータになります。これは、コピーが作成されるべき場所に参照がぶら下がっているように見えますが、場所が見つからず、との外でこれを再現することはできません。lmupdatelmupdate

具体的な例:

アイリスデータから始めて、最初に3つの種の異なるサンプルサイズを作成し、次に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

そして、最初の適合はこれを確認します:

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

しかし、更新された2番目のフィットは、すべてのモデルで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
4

1 に答える 1

6

これは答えではありませんが、コメントするには長すぎます

.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

長期的な解決策ではありませんが、少なくとも回避策です。

于 2013-03-13T04:07:53.380 に答える