在交互模式下,探索data.table中的聚合时,我可能会进行数十个或数百个实验。在编写了生成聚合所需的最少代码量之后,聚合之后的默认列名(V1
,V2
等)显然不是很有帮助。通常,我更喜欢使用一列的简单聚合的默认列名,例如均值或总和,只是基础变量的名称。
所有多余的列名称键入都会很累,我想避免这种情况。
在data.table
中有什么简单的方法可以做到这一点?
例如一个简化的示例来演示不清楚的地方:
DT = data.table(x =rep(c("b","a","c"),each=3), y_a_long_name=c(1,3,6), v_a_long_name=1:9)
DT[, .(sum(v_a_long_name), mean(y_a_long_name)), by = x]
# x V1 V2
# 1: b 6 3.333333
# 2: a 15 3.333333
# 3: c 24 3.333333
当您开始使用不同的聚合类型函数处理多个列时,上面的标签V1
,V2
并没有帮助。
重复名称的所有其他额外输入都很乏味,但是我希望看到这样的内容:
DT[, .(v_a_long_name = sum(v_a_long_name), y_a_long_name = mean(y_a_long_name)), by = x]
# x v_a_long_name y_a_long_name
# 1: b 6 3.333333
# 2: a 15 3.333333
# 3: c 24 3.333333
,同时输入尽可能少的字符。例如
DT[, .(sum(v_a_long_name), mean(y_a_long_name)), by = x]
默认打印此:
# x v_a_long_name y_a_long_name
# 1: b 6 3.333333
# 2: a 15 3.333333
# 3: c 24 3.333333
答案 0 :(得分:2)
我们可以使用setNames
包裹列的list
DT[, setNames(.(sum(v_a_long_name), mean(y_a_long_name)), names(DT)[2:3]), by = x]
# x y_a_long_name v_a_long_name
#1: b 6 3.333333
#2: a 15 3.333333
#3: c 24 3.333333
或在获得输出后使用setnames
setnames(DT[, .(sum(v_a_long_name), mean(y_a_long_name)),
by = x], 2:3, names(DT)[2:3])[]
或者通过从.SD
提取列来使其更紧凑
setnames(DT[, .(sum(.SD[[2]]), mean(.SD[[1]])), by = x], 2:3, names(DT)[2:3])[]
答案 1 :(得分:1)
有些回旋解决方案,但是您可以将函数列表和列列表传递给Map
+ do.call
。结果列的名称将从Map
的第一个参数获取,这意味着您只需在.SDcols
中以长格式指定一次名称:
DT[,
Map(do.call, args=lapply(.SD,list), what=c(sum,mean)),
by=x, .SDcols=c("v_a_long_name","y_a_long_name")
]
# x v_a_long_name y_a_long_name
#1: b 6 3.333333
#2: a 15 3.333333
#3: c 24 3.333333
如果需要自动命名,则可以提前定义变量:
nms <- c("v_a_long_name","y_a_long_name")
funs <- c("sum","mean")
DT[,
setNames(Map(do.call, args=lapply(.SD,list), what=funs), paste(nms,funs,sep="_")),
by=x, .SDcols=nms
]
# x v_a_long_name_sum y_a_long_name_mean
#1: b 6 3.333333
#2: a 15 3.333333
#3: c 24 3.333333