1. ホーム
  2. r

[解決済み] dplyr で文字列ベクトル入力を使って複数列でグループ化する

2022-04-23 20:01:30

質問

plyrの理解をdplyrに移そうとしているのですが、複数のカラムでグループ化する方法が分かりません。

# make data with weird column names that can't be hard coded
data = data.frame(
  asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
  a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
  value = rnorm(100)
)

# get the columns we want to average within
columns = names(data)[-3]

# plyr - works
ddply(data, columns, summarize, value=mean(value))

# dplyr - raises error
data %.%
  group_by(columns) %.%
  summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds

plyr の例を dplyr 風の構文に翻訳するには、何が足りないのでしょうか?

2017年版を編集する : Dplyrがアップデートされたので、よりシンプルなソリューションが利用できます。現在選択されている回答を参照してください。

どのように解決するのですか?

この質問が投稿された後、dplyr は group_by ( ドキュメントはこちら ). これによって select というように。

data = data.frame(
    asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
    a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
    value = rnorm(100)
)

# get the columns we want to average within
columns = names(data)[-3]

library(dplyr)
df1 <- data %>%
  group_by_at(vars(one_of(columns))) %>%
  summarize(Value = mean(value))

#compare plyr for reference
df2 <- plyr::ddply(data, columns, plyr::summarize, value=mean(value))
table(df1 == df2, useNA = 'ifany')
## TRUE 
##  27 

あなたの質問例からの出力は予想通りです(上のplyrとの比較と下の出力を参照)。

# A tibble: 9 x 3
# Groups:   asihckhdoydkhxiydfgfTgdsx [?]
  asihckhdoydkhxiydfgfTgdsx a30mvxigxkghc5cdsvxvyv0ja       Value
                     <fctr>                    <fctr>       <dbl>
1                         A                         A  0.04095002
2                         A                         B  0.24943935
3                         A                         C -0.25783892
4                         B                         A  0.15161805
5                         B                         B  0.27189974
6                         B                         C  0.20858897
7                         C                         A  0.19502221
8                         C                         B  0.56837548
9                         C                         C -0.22682998

ただし dplyr::summarize はグループ化のレイヤーを一度にひとつずつ取り除くだけなので、 結果のティブルの中ではまだグループ化が行われています (これは後で人々を驚かせることになります)。予期せぬグループ化動作から絶対に逃れたいのであれば、常に %>% ungroup を要約した後、パイプラインに追加します。