【发布时间】:2018-11-25 11:02:13
【问题描述】:
谁能帮我理解为什么下面两个版本的 lapply 操作使用和不使用 get() 不会产生相同的结果?使用 get() 时,结果列会混淆。
dt <- data.table(v1 = c(1,2), v2 = c(3,4), type = c('A', 'B'))
v1 v2 type
1: 1 3 A
2: 2 4 B
col_in <- c('v2', 'v1')
col_out <- paste0(col_in, '.new')
以硬编码方式访问“类型”
dt[, (col_out) := lapply(.SD, function(x){x * min(x[type == 'A'])}), .SDcols = col_in]
产生预期的结果:
v1 v2 type v2.new v1.new
1: 1 3 A 9 1
2: 2 4 B 12 2
但是,当通过 get() 访问“类型”时
dt[, (col_out) := lapply(.SD, function(x){x * min(x[get('type') == 'A'])}), .SDcols = col_in]
v1.new 的预期值在 v2.new 中,反之亦然:
v1 v2 type v2.new v1.new
1: 1 3 A 1 9
2: 2 4 B 2 12
注意:这是我从尝试实现的更复杂操作中提炼出来的最小玩具示例。 'type' 变量的名称作为输入参数给出。
【问题讨论】:
-
很奇怪,添加
get("type")改变了 x 的顺序。如果在函数调用中添加print(x),您可以看到更改。如果你这样做col_in <- sort(col_in)这不再是问题。 -
如果您想要替代方案,请将
get("type")更改为dt[["type"]]works -
如果
names(dt)不等于sort(names(dt)),则使用sort(col_in)选项不起作用,如果您按组进行这些计算,则使用dt[['type']]不起作用。对于第三个选项,您可以使用:col_in <- col_in[match(col_in, names(dt))] -
你可能知道,这可行,尽管它增加了两个对
[.data.table的调用:dt[, (col_out) := lapply(.SD[, col_in, with = F], function(x){x * min(x[.SD[, 'type', with = F] == 'A'])})] -
我还注意到它与 data.table 中列的顺序和/或“col_in”向量有关。也许有人仍然可以评论执行这些类型的操作的“正确”(+高效+可读)方式是为了避免糟糕的意外。在我的实际代码中,我确实也按其他变量分组。作为一种解决方法,我遍历输入列以一次计算一个结果列,但这是以一遍又一遍地计算分组为代价的。
标签: r data.table lapply