tidyverseでデータフレームをグループ別に処理する場合、dplyrパッケージのgroup_by関数を使います。group_by関数以降の処理では、グループ毎に計算が行われます。Rの標準的な操作なら、apply系関数を使って同じような処理を行えます。
行をグループ毎に分ける
dplyrパッケージのgroup_by関数を使えば、データフレームから行をグループ毎に分けることができます。グループ分けは列名を指定し、複数指定してより細かいグループに分けることもできます。グループ分けした後、summarize関数やfilter関数などを使って、グループ毎の計算を行います。tidyverseパッケージをロードすると使えるようになります。
書式
group_by関数は、第1引数にデータ、第2引数以降にグループ分けする列名を指定します。グループ分けに使う列は、列挙して複数指定できます。尚、パイプ(%>%)を使って連続的に処理を記述する場合は、第1引数のデータは省略することができます。
> summarize or filter((group_by(データ, グループ列1, グループ列2), 計算式) > データ %>% group_by(グループ列1, グループ列2) %>% summarize or filter(計算式)
グループに処理を行う
単純なグループ
group_by関数によるグループ分けは「Species」のみを指定して、グループ毎(Species毎)に「Petal.Width」のtop2(大きいものから2個)を抽出しました。
1: > iris %>% group_by(Species) %>% top_n(2, Petal.Width) 2: # A tibble: 7 x 5 3: # Groups: Species [3] 4: Sepal.Length Sepal.Width Petal.Length Petal.Width Species 5: <dbl> <dbl> <dbl> <dbl> <fct> 6: 1 5.1 3.3 1.7 0.5 setosa 7: 2 5 3.5 1.6 0.6 setosa 8: 3 5.9 3.2 4.8 1.8 versicolor 9: 4 6.7 3 5 1.7 versicolor 10: 5 6.3 3.3 6 2.5 virginica 11: 6 7.2 3.6 6.1 2.5 virginica 12: 7 6.7 3.3 5.7 2.5 virginica
複数指定したグループ
group_by関数によるグループ分けで「id」のみを指定した場合と、複数「id」「number」を指定してより細かいグループ分けをした場合を比較しました。前者は、A・Bからなる2つのグループ分けなので、それぞれの行数は2行・1行。後者は、A_10, B_20、A_30のグループで3つに分かれたので、それぞれの行数は1行ずつになりました。グループの分けかたによって、以降の処理結果が変わることがわかります。
1: > my_data <- data.frame(id=c("A", "B", "A"), number=c(10, 20, 30)) 2: > my_data 3: id number 4: 1 A 10 5: 2 B 20 6: 3 A 30 7: 8: > my_data %>% group_by(id) %>% mutate(lines = n()) 9: # A tibble: 3 x 3 10: # Groups: id [2] 11: id number lines 12: <fct> <dbl> <int> 13: 1 A 10 2 14: 2 B 20 1 15: 3 A 30 2 16: 17: > my_data %>% group_by(id, number) %>% mutate(lines = n()) 18: # A tibble: 3 x 3 19: # Groups: id, number [3] 20: id number lines 21: <fct> <dbl> <int> 22: 1 A 10 1 23: 2 B 20 1 24: 3 A 30 1
グループ毎にまとめる
group_by関数によるグループ分けは「Species」のみを指定して、グループ毎(Species毎)に集計(summarize)しました。「number」をグループ毎にreduce関数で加算し(A:10+30, B:20)、add列に整理しました。
1: > my_data 2: id number 3: 1 A 10 4: 2 B 20 5: 3 A 30 6: 7: > my_data %>% group_by(id) %>% summarize(add = purrr::reduce(number, `+`)) 8: id add 9: <fct> <dbl> 10: 1 A 40 11: 2 B 20
Rの標準的な操作
データフレームに対してグループ毎に集計などの処理を行う場合、Rの標準的な方法ではapply系関数を使うと同じような処理を行うことができます。例ではtapplyを使いました。データフレーム([行,列])のfactorでグループ分けされている列に対して、グループ毎の加算行いました。tapplyには、処理対象の列、グループ毎のファクターのリスト、処理内容を与えました。
1: > my_data 2: id number 3: 1 A 10 4: 2 B 20 5: 3 A 30 6: 7: > attach(my_data) 8: 9: > id 10: A B A 11: Levels: A B 12: 13: > tapply(number, id, sum) 14: A B 15: 40 20
まとめ
- tidyverseでデータフレームをグループ別に処理する場合、dplyrパッケージのgroup_by関数を使う。
- group_by関数で分けた後は、グループ毎に集計などが可能で、summarizeやfilterなどが用いられることが多い。
- Rの標準的な操作なら、apply系関数で同じような処理が可能。
論文・データ解析の支援
個別に直接相談できるのが良いと、たくさんの方にご利用頂いています。