[英]data.table column order when using lapply and get
有人可以帮助我理解为什么下面的两个版本的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()访问'type'时
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需要一些内部排序(bug?)。
避免这种情况的两种方法:
将类型=='A'部分移到dt [,lapply(...)]之外
referenceRows <- which(dt[,type == 'A']) referenceRows <- which(dt[,get('type') == 'A']) dt[, lapply(.SD, function(x){x * min(x[referenceRows])}), .SDcols = col_in] v1 v2 type v2.new v1.new 1: 1 3 A 9 1 2: 2 4 B 12 2
首先创建新列,然后使用setnames确保为新列分配正确的列名称。 最后用cbind将这两个部分绑定在一起:
dtNew <- dt[, lapply(.SD, function(x){x * min(x[type == 'A'])}), .SDcols = col_in] setnames(dtNew, col_in, col_out) cbind(dt, dtNew) v1 v2 type v2.new v1.new 1: 1 3 A 9 1 2: 2 4 B 12 2
相同的结果(虽然排序不同):
dtNew <- dt[, lapply(.SD, function(x){x * min(x[get('type') == 'A'])}), .SDcols = col_in]
setnames(dtNew, col_in, col_out)
cbind(dt, dtNew)
v1 v2 type v1.new v2.new
1: 1 3 A 1 9
2: 2 4 B 2 12
另一种方法是在语言上使用称为计算的酷R特性(与data.table无关),而不是使用substitute
函数get
并生成所需的j
参数作为语言对象。
这在分组时也适用。
library(data.table)
dt <- data.table(v1 = c(1,2), v2 = c(3,4), type = c('A', 'B'))
col_in <- c('v2', 'v1')
col_out <- paste0(col_in, '.new')
col_where <- 'type'
qj <- substitute(.col_out := lapply(.SD, function(x){x * min(x[.col_where == 'A'])}),
list(.col_out=col_out, .col_where=as.name(col_where)))
print(qj)
#`:=`(c("v2.new", "v1.new"), lapply(.SD, function(x) {
# x * min(x[type == "A"])
#}))
dt[, eval(qj), .SDcols = col_in][]
# v1 v2 type v2.new v1.new
# <num> <num> <char> <num> <num>
#1: 1 3 A 9 1
#2: 2 4 B 12 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.