32

別の列でグループ化された、data.tableのいくつかの列のそれぞれの平均を計算したいと思います。私の質問は、SOに関する他の2つの質問(1つと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
4

1 に答える 1

45

使用する必要があります.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 の編集: (却下されました): 詳細について.SDは、この投稿を参照してください。これはここに関連していると思います。ありがとう@デビッド。

編集 2:data.table 1000 行と 301 列 (グループ化用の 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)]
    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 は指定した列のみで提供されます。

お役に立てれば。

于 2013-02-18T13:20:36.353 に答える