Dav*_*d D 32 r data.table
我想计算data.table中每个列的平均值,按另一列分组.我的问题类似于关于SO的另外两个问题(一个和两个),但我不能将这些问题应用于我的问题.
这是一个例子:
library(data.table)
dtb <- fread(input = "condition,var1,var2,var3
one,100,1000,10000
one,101,1001,10001
one,102,1002,10002
two,103,1003,10003
two,104,1004,10004
two,105,1005,10005
three,106,1006,10006
three,107,1007,10007
three,108,1008,10008
four,109,1009,10009
four,110,1010,10010")
dtb
# condition var1 var2 var3
# 1: one 100 1000 10000
# 2: one 101 1001 10001
# 3: one 102 1002 10002
# 4: two 103 1003 10003
# 5: two 104 1004 10004
# 6: two 105 1005 10005
# 7: three 106 1006 10006
# 8: three 107 1007 10007
# 9: three 108 1008 10008
# 10: four 109 1009 10009
# 11: four 110 1010 10010
Run Code Online (Sandbox Code Playgroud)
每个单一均值的计算很容易; 例如,对于"VAR1": dtb[ , mean(var1), by = condition]
.但是如果有很多变量并且你需要编写所有变量,我很快就会变得很麻烦.因此,dtb[, list(mean(var1), mean(var2), mean(var3)), by = condition]
是不希望的.我需要列名是动态的,我希望最终得到这样的东西:
condition var1 var2 var3
1: one 101.0 1001.0 10001.0
2: two 104.0 1004.0 10004.0
3: three 107.0 1007.0 10007.0
4: four 109.5 1009.5 10009.5
Run Code Online (Sandbox Code Playgroud)
Aru*_*run 43
您应该使用.SDcols
(特别是如果您有太多列,并且您需要仅对列的子集执行特定操作(除了分组变量列).
dtb[, lapply(.SD, mean), by=condition, .SDcols=2:4]
# condition var1 var2 var3
# 1: one 101.0 1001.0 10001.0
# 2: two 104.0 1004.0 10004.0
# 3: three 107.0 1007.0 10007.0
# 4: four 109.5 1009.5 10009.5
Run Code Online (Sandbox Code Playgroud)
您还可以在变量中获取您想要的所有列名称,然后将其传递给.SDcols
如下:
keys <- setdiff(names(dtb), "condition")
# keys = var1, var2, var3
dtb[, lapply(.SD, mean), by=condition, .SDcols=keys]
Run Code Online (Sandbox Code Playgroud)
编辑:正如Matthew Dowle正确地指出的那样,因为你需要在分组之后在每个其他列上计算平均值condition
,你可以这样做:
dtb[, lapply(.SD, mean), by=condition]
Run Code Online (Sandbox Code Playgroud)
大卫的编辑:(被拒绝):.SD
从这篇文章了解更多.我发现这与此相关.谢谢@David.
编辑2:假设您有data.table
1000行和301列(一列用于分组和300个数字列):
require(data.table)
set.seed(45)
dt <- data.table(grp = sample(letters[1:15], 1000, replace=T))
m <- matrix(rnorm(300*1000), ncol=300)
dt <- cbind(dt, m)
setkey(dt, "grp")
Run Code Online (Sandbox Code Playgroud)
你想找到列的平均值,比如251:300,
您可以计算所有列的平均值,然后对这些列进行子集(这对于计算整个数据而言效率不高).
dt.out <- dt[, lapply(.SD, mean), by=grp]
dim(dt.out) # 15 * 301, not efficient.
Run Code Online (Sandbox Code Playgroud)你可以将data.table
第一列过滤到这些列,然后计算均值(这也不一定是最好的解决方案,因为每次你想要对某些列进行操作时你必须创建一个额外的子集data.table.
dt.sub <- dt[, c(1, 251:300)]
setkey(dt.sub, "grp")
dt.out <- dt.sub[, lapply(.SD, mean), by=grp]
Run Code Online (Sandbox Code Playgroud)您可以像往常一样逐个指定每个列(但这对于较小的data.tables来说是可取的)
# if you just need one or few columns
dt.out <- dt[, list(m.v251 = mean(V251)), by = grp]
Run Code Online (Sandbox Code Playgroud)那么什么是最好的解决方案?答案是.SDcols.
如文档状态,对于一个data.table X,.SDcols指定被包括在列.SD.
这基本上隐式地过滤了将传递给.SD而不是创建子集的列(如前所述),只有它非常高效且快速!
我们应该怎么做?
通过指定列号:
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = 251:300]
dim(dt.out) # 15 * 51 (what we expect)
Run Code Online (Sandbox Code Playgroud)或者通过指定列ID:
ids <- paste0("V", 251:300) # get column ids
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = ids]
dim(dt.out) # 15 * 51 (what we expect)
Run Code Online (Sandbox Code Playgroud)它接受列名和数字作为参数.在这两种情况下,.SD仅与我们指定的列一起提供.
希望这可以帮助.
归档时间: |
|
查看次数: |
15564 次 |
最近记录: |