我在学习 data.table
的过程中,发现一个我无法优雅地解决的情况。
提前说明: lm
公式的荒谬是显而易见的,我正在尝试确定是否可以通过 data.table
生态系统内的关键字或特殊运算符轻松解决这个细微差别。
library(data.table)
mt <- as.data.table(mtcars)
mt[, list(model = list(lm(mpg ~ disp))), by = "cyl"]
# cyl model
# 1: 6 <lm>
# 2: 4 <lm>
# 3: 8 <lm>
mt[, list(model = list(lm(mpg ~ disp + cyl))), by = "cyl"]
# Error in model.frame.default(formula = mpg ~ disp + cyl, drop.unused.levels = TRUE) :
# variable lengths differ (found for 'cyl')
由于在此块内,
cyl
是长度为1的向量,而不是像其他值一样的列:mt[, list(model = { browser(); list(lm(mpg ~ cyl+disp)); }), by = "cyl"]
# Called from: `[.data.table`(mt, , list(model = {
# browser()
# list(lm(mpg ~ cyl + disp))
# ...
# Browse[1]>
# debug at #1: list(lm(mpg ~ cyl + disp))
# Browse[2]>
disp
# [1] 160.0 160.0 258.0 225.0 167.6 167.6 145.0
# Browse[2]>
cyl
# [1] 6
似乎最简单的方法是在需要时手动将其内部作为临时变量或直接进行长度加长:
mt[, list(model = { cyl2 <- rep(cyl, nrow(.SD)); list(lm(mpg ~ cyl2+disp)); }), by = "cyl"]
mt[, list(model = list(lm(mpg ~ rep(cyl, nrow(.SD))+disp))), by = "cyl"]
问题:有没有更优雅的方法来处理这个问题?
各种松散相关的问题,引发了我的好奇心(对于在DT对象中嵌入“东西”):
目前的候选人很多,都很不错:
mt[, .(model = .(lm(mpg ~ cyl + disp, data = mt[.I]))), by = .(cyl)]
mt[, .(model = .(lm(mpg ~ cyl + disp))), by =.(cylgroup=cyl)]
mt[, .(model = .(lm(mpg ~ cyl + disp, .SD))), by=cyl, .SDcols=names(mt)]
mt[, .(model = .(lm(mpg ~ cyl + disp, .SD))), by=cyl, .SDcols=TRUE]
mt[, .(model = .(lm(mpg ~ cyl + disp, data = cbind(.SD, as.data.table(.BY))))), by = "cyl"]
J
内部创建列,您可以制作重复的“cyl”列,然后使用它? - Mike H.by=
的名称 -mt[, length(cyl), by = .(cylgroup=cyl)]
。 - thelatemail.SDcols=
参数引用cyl
-mt[, .(.(lm(mpg ~ cyl + disp, .SD))), by=cyl, .SDcols=names(mt)]
或者甚至是mt[, .(.(lm(mpg ~ cyl + disp, .SD))), by=cyl, .SDcols=TRUE]
。 - thelatemailmtm = mt[, list(model = list(lm(mpg ~ disp + cyl, data = cbind(.SD, as.data.table(.BY))))), by = "cyl"]
- Frank