pal*_*czy 27 r data.table
我正在尝试将多个函数应用于a的多个列data.table.例:
DT <- data.table("a"=1:5,
"b"=2:6,
"c"=3:7)
Run Code Online (Sandbox Code Playgroud)
比方说,我想要得到的平均值和列的中位数a和b.这有效:
stats <- DT[,.(mean_a=mean(a),
median_a=median(a),
mean_b=mean(b),
median_b=median(b))]
Run Code Online (Sandbox Code Playgroud)
但这太重复了.有没有一种很好的方法来使用.SDcols和获得类似的结果lapply?
edd*_*ddi 29
我通常这样做:
my.summary = function(x) list(mean = mean(x), median = median(x))
DT[, unlist(lapply(.SD, my.summary)), .SDcols = c('a', 'b')]
#a.mean a.median b.mean b.median
# 3 3 4 4
Run Code Online (Sandbox Code Playgroud)
Col*_*vel 11
这有点笨拙,但做的工作是data.table:
funcs = c('median', 'mean', 'sum')
m = DT[, lapply(.SD, function(u){
sapply(funcs, function(f) do.call(f,list(u)))
})][, t(.SD)]
colnames(m) = funcs
# median mean sum
#a 3 3 15
#b 4 4 20
#c 5 5 25
Run Code Online (Sandbox Code Playgroud)
其他答案显示了如何执行此操作,但是没有人愿意去解释基本原理。基本规则是,j表达式返回的列表元素构成结果的列data.table。任何j产生列表的表达式都可以使用,该列表的每个元素都对应于结果中所需的列。考虑到这一点,我们可以使用
DT[, c(mean = lapply(.SD, mean),
median = lapply(.SD, median)),
.SDcols = c('a', 'b')]
## mean.a mean.b median.a median.b
## 1: 3 4 3 4
Run Code Online (Sandbox Code Playgroud)
要么
DT[, unlist(lapply(.SD,
function(x) list(mean = mean(x),
median = median(x))),
recursive = FALSE),
.SDcols = c('a', 'b')]
## a.mean a.median b.mean b.median
## 1: 3 3 4 4
Run Code Online (Sandbox Code Playgroud)
取决于所需的顺序。
重要的是,只要如上所述将结果排列到列表中,我们就可以使用想要产生期望结果的任何方法。例如,
library(matrixStats)
DT[, c(mean = as.list(colMeans(.SD)),
median = setNames(as.list(colMedians(as.matrix(.SD))), names(.SD))),
.SDcols = c('a', 'b')]
## mean.a mean.b median.a median.b
## 1: 3 4 3 4
Run Code Online (Sandbox Code Playgroud)
也可以。