我想在for循环中更新data.table中的某些列。列名是动态设置的。不幸的是,我使用的解决方案太慢了,因此不可行。我已经尝试了有关该主题的所有内容,但似乎没有使它更快的方法。
我的数据集有682446行。似乎如此之慢的是动态列名称。当我使用静态版本时,它工作得很好并且速度很快:
dt[education>0, educationNewVersion:=education]
当i,j(LHS,RHS)中的变量名称是动态的时,就会出现问题:
varName = 'education'
newVarName <- paste0(varName, 'NewVersion')
# This is much slower as the static version from above, takes almost half a minute.
dt[dt[[varName]]>0, (newVarName):=get(varName)]
# This is very slow too
dt[dt[[varName]]>0, (newVarName):=eval(varName)]
# This one throws an error (see below)
dt[dt[[varName]]>0, (newVarName):=dt[[varName]]]
这是第三个表达式引发的错误:“已将682446项分配给'gerSpeakImp'列的76451项。如果您想'回收'RHS,请使用rep()使此意图对您的代码读者清楚。”
请不要建议我使用set()。set()不支持分组,我需要分组(为了使示例简单起见,这里没有包括在内)。我不知道该怎么办。目前,我正在用自己的语句更新每一列,这实际上是非常多余的,这不是我从Stata移至R(以及移至data.table)时的预期。
使用.I
和可能更好.SDcols
。
dt[dt[, .I[.SD[[1]] > 0], .SDcols = varName], (newVarName) := .SD[[1]],
.SDcols = varName]
在第三个表达式中,发生错误是因为它试图从长度不同的整个数据集中对列进行子集化。相反,我们可以使用.SD
dt[dt[[varName]]>0, (newVarName):= .SD[[varName]]]
set.seed(24)
dt <- data.table(education = sample(0:50, 682446, replace = TRUE))
dt1 <- copy(dt)
varName <- 'education'
newVarName <- paste0(varName, 'NewVersion')
system.time(dt[dt[[varName]]>0, (newVarName):= .SD[[varName]]])
# user system elapsed
# 0.022 0.003 0.026
system.time( dt1[dt1[, .I[.SD[[1]] > 0], .SDcols = varName],
(newVarName) := .SD[[1]],
.SDcols = varName])
# user system elapsed
# 0.023 0.003 0.024
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句