好的,这是一个奇怪的问题。我怀疑这是 data.table
内部的一个 bug,但如果有人能解释为什么会发生这种情况 - update
到底在做什么,那就太有用了。
我在使用 data.table
中的 list(list())
技巧来存储拟合模型。当您创建一系列针对不同分组的 lm
对象,然后更新这些模型时,所有模型的模型数据都变成了最后一组的模型数据。这似乎像是某个引用挂在了某个地方,而应该制作副本,但我找不到在 lm
和 update
之外复现此问题的方法。
具体示例:
从鸢尾花数据开始,首先使三个物种具有不同的样本大小,然后对每个物种拟合一个 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
但更新后的第二个适配器对所有型号都显示为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
m1 <- fit$V1[[2]]; m2 <- update(m1, .~.)
;m1
和m2
会变得不同。或许这会有助于解决问题。 - Aaron left Stack Overflowdata.table
中时它会在哪里查找呢?值得注意的是它并没有捕获整个data.table
列 - 只有最终分组的列。 - Corvus