data.table循环动态计算分组时,如何自定义分组列名?
解决data.table循环中动态命名分组列的问题
示例数据
library(data.table) # dummy data df <- data.table(metric_1 = c(1,1,3) , metric_2 = c(1,2,2) ); df
输出:
metric_1 metric_2 1: 1 1 2: 1 2 3: 3 2
问题描述
需要循环处理指定列,先对每列执行fifelse转换(将1替换为0,其余值保留),再按转换结果分组统计行数。当前代码能生成统计结果,但分组列默认名为fifelse;尝试直接在by参数中用原列名命名时触发语法错误:
错误代码:
# metric columns x <- c('metric_1', 'metric_2') # list to capture results y <- vector('list', length(x)) for (i in seq_along(x)) { y[[i]] <- df[, .(rows = .N) , by = .(x[[i]] = fifelse(get(x[[i]]) == 1, 0, get(x[[i]]))) ] }
报错信息:
Error: unexpected '=' in: " df[, .(rows = .N) , by = .(x[[i]] ="
解决方案
方法1:分组后重命名列(兼容所有data.table版本)
先按转换结果分组统计,再用setnames将默认的fifelse列名替换为原列名:
x <- c('metric_1', 'metric_2') y <- vector('list', length(x)) for (i in seq_along(x)) { # 先执行分组统计 temp_result <- df[, .(rows = .N), by = .(fifelse(get(x[[i]]) == 1, 0, get(x[[i]])))] # 重命名分组列为原列名 setnames(temp_result, old = "fifelse", new = x[[i]]) y[[i]] <- temp_result } # 查看结果 y
输出结果:
[[1]] metric_1 rows 1: 0 2 2: 3 1 [[2]] metric_2 rows 1: 0 1 2: 2 2
方法2:动态构建命名分组列表(更简洁)
通过setNames创建以原列名为键的分组列表,直接传递给by参数:
x <- c('metric_1', 'metric_2') y <- vector('list', length(x)) for (i in seq_along(x)) { # 构建命名分组列 by_group <- setNames( list(fifelse(get(x[[i]]) == 1, 0, get(x[[i]]))), nm = x[[i]] ) # 执行分组统计 y[[i]] <- df[, .(rows = .N), by = by_group] }
报错原因
data.table的by=.()语法本质是调用list(),而在list()中无法直接用变量(如x[[i]])作为列名赋值,必须通过命名列表或事后重命名的方式实现动态列名。
内容的提问来源于stack exchange,提问作者Sweepy Dodo
相关产品推荐
相关产品推荐

