我正在尝试将多个函数应用于data.table
的多个列。例如:
DT <- data.table("a"=1:5,
"b"=2:6,
"c"=3:7)
我想说我想得到列a
和b
的平均值和中位数。
这有效:
stats <- DT[,.(mean_a=mean(a),
median_a=median(a),
mean_b=mean(b),
median_b=median(b))]
但这太重复了。有没有一种很好的方法可以使用.SDcols
和lapply
来获得类似的结果?
答案 0 :(得分:24)
我通常会这样做:
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
答案 1 :(得分:8)
这有点笨拙但用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
答案 2 :(得分:3)
其他答案显示了如何执行此操作,但是没有人愿意解释基本原理。基本规则是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
或
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
取决于所需的顺序。
重要的是,只要如上所述将结果排列到列表中,我们就可以使用任何想要产生期望结果的方法。例如,
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
也可以。
答案 3 :(得分:1)
使用dcast
DT$dday <- 1 # add a constant column
dt <- dcast(DT, dday~dday, fun=list(sum, mean), value.var = c('a', 'b'))
# dday a_sum_1 b_sum_1 a_mean_1 b_mean_1
# 1 15 20 3 4
事实上,我们可以使用dcast实现onehot和功能工程师。
答案 4 :(得分:0)
这可能有点过分设计,但是如果您来自dplyr的summarize_at()
,则可能希望获得类似的结构化结果。
首先定义一个函数lapply_at()
,该函数将一个.SD
和一个函数名称的字符向量作为输入。然后,您可以轻松计算所需的统计信息并获得可读的结果。
library(data.table)
iris_dt <- as.data.table(iris)
lapply_at <- function(var, funs, ...) {
results <- sapply(var, function(var) {
lapply(funs, do.call, list(var, ...))
})
names(results) <- vapply(names(var), paste, funs, sep = "_",
FUN.VALUE = character(length(funs)),
USE.NAMES = FALSE)
results
}
iris_dt[, lapply_at(.SD, c("mean", "sd"), na.rm = TRUE),
.SDcols = patterns("^Sepal"),
by = Species]
#> Species Sepal.Length_mean Sepal.Length_sd Sepal.Width_mean
#> 1: setosa 5.006 0.3524897 3.428
#> 2: versicolor 5.936 0.5161711 2.770
#> 3: virginica 6.588 0.6358796 2.974
#> Sepal.Width_sd
#> 1: 0.3790644
#> 2: 0.3137983
#> 3: 0.3224966
由reprex package(v0.2.0)于2019-07-03创建。