別の列でグループ化されたdata.tableのいくつかの列のそれぞれの平均を計算したいと思います。私の質問は、SO( one and two ))に関する他の2つの質問と似ていますが、問題に適用できませんでした。
次に例を示します。
_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
_
各単一平均の計算は簡単です。例えば「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
_
.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
次のように、最初に変数で取得したいすべての列名を取得し、それを.SDcols
に渡すこともできます。
keys <- setdiff(names(dtb), "condition")
# keys = var1, var2, var3
dtb[, lapply(.SD, mean), by=condition, .SDcols=keys]
編集:Matthew Dowleが正しく指摘したように、condition
でグループ化した後、他のすべての列で平均を計算する必要があるので、ただ:
dtb[, lapply(.SD, mean), by=condition]
Davidの編集:(拒否されました): thisから.SD
の詳細を読みますpost 。これはここに関連があると思います。 @Davidに感謝します。
編集2:1000行と301列のdata.table
があるとします(グループ化用の1列と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")
そして、列の平均、たとえば251:300だけを見つけたいと思ったとします。
すべての列の平均を計算してから、これらの列をサブセット化できます(データ全体で計算するため、これはあまり効率的ではありません)。
dt.out <- dt[, lapply(.SD, mean), by=grp]
dim(dt.out) # 15 * 301, not efficient.
最初にdata.table
をフィルタリングしてこれらの列だけにしてから、平均を計算できます(特定の列で操作が必要になるたびに追加のサブセット化されたdata.tableを作成する必要があるため、これも必ずしも最良の解決策ではありません。
dt.sub <- dt[, c(1, 251:300), with=FALSE]
setkey(dt.sub, "grp")
dt.out <- dt.sub[, lapply(.SD, mean), by=grp]
通常どおりに各列を1つずつ指定できます(ただし、これは小さなdata.tablesに適しています)
# if you just need one or few columns
dt.out <- dt[, list(m.v251 = mean(V251)), by = grp]
それで、最善の解決策は何ですか?答えは。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)
または、列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)
引数として列名と数値の両方を受け入れます。どちらの場合も、.SDには、指定したこれらの列のみが提供されます。
お役に立てれば。