如何用data.table实现dplyr的group_by+mutate(across)且保留非处理列
等效的data.table写法(保留所有列)
要实现和dplyr代码完全等效的效果(分组转换指定列且保留其他列),你需要使用data.table的原地更新操作符:=,而不是直接返回.SD的计算结果。具体代码如下:
library(data.table) # 先将mtcars转换为data.table(如果还不是的话) setDT(mtcars) # 分组更新指定列,保留其他所有列 mtcars[, (mpg:qsec) := lapply(.SD, function(x) x / sum(x)), .SDcols = mpg:qsec, by = vs]
代码说明:
:=是data.table的核心原地更新语法,它会直接修改目标列,而不会丢弃其他未指定的列(比如am、gear、carb),这和dplyr中mutate的行为完全一致。(mpg:qsec)用括号包裹列范围,是为了将列名表达式的结果作为要更新的列名,确保批量修改指定范围的列。.SDcols = mpg:qsec限定.SD(Subset of Data)只包含mpg到qsec的列,避免对其他列做不必要的处理。by = vs指定分组依据,和dplyr的group_by(vs)作用相同。
不修改原数据的方案:
如果不想直接修改原始的mtcars,可以先复制一份再操作:
mtcars_modified <- copy(mtcars) mtcars_modified[, (mpg:qsec) := lapply(.SD, \(x) x / sum(x)), .SDcols = mpg:qsec, by = vs]
为什么你之前的写法会丢失列?
你之前的代码mtcars[, lapply(.SD, function(x) { x/sum(x) }), .SDcols = mpg:qsec, by = vs]是直接返回分组后处理的.SD结果,这会生成一个只包含分组列和.SDcols指定列的新data.table,自然会丢失其他未包含在.SDcols里的列。而使用:=则是在原数据结构上更新指定列,其他列会被完整保留。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

