こんにちは,shun(@datasciencemore)です!
今回はグルーピングについてやっていきます.
グルーピングって聞くだけでなんとなく何をするかわかると思います.
要は,データフレーム全体ではなく,各分類ごとにデータを見るってことです.
どんな感じなのか,さっそく見ていきましょう.
0.グルーピングってなに??
データを処理する際,ある特定の条件でまとめて,それぞれで処理するということは頻出です.
それでは,具体例を交えて説明していきますね.
1.基本
例えば次のような例を考えてみましょう.
今,とある高校の1学年あたりのデータフレームがあるとします.
そのデータには,クラス(= class),性別( = gender),身長( = height)があります.
1 2 3 4 5 6 7 |
# データフレームを定義 df = tibble( class = c("a", "b", "c", "c", "a", "c", "b", "a", "c", "b", "a"), gender = c("M", "F", "F", "M", "F", "M", "M", "F", "M", "M", "F"), height = c(162, 150, 168, 173, 162, 198, 182, 154, 175, 160, 172) ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
> df # A tibble: 11 x 3 class gender height <chr> <chr> <dbl> 1 a M 162 2 b F 150 3 c F 168 4 c M 173 5 a F 162 6 c M 198 7 b M 182 8 a F 154 9 c M 175 10 b M 160 11 a F 172 |
さて,クラスごとに生徒の身長の平均を求めたい場合はどうすればいいでしょうか?
えーと,
①クラスごとにデータフレームを分割する.
②分割したデータフレームごとに身長を平均する.
とすればいけそうね.
はい,その通りです!
これらの処理は,それぞれ,group_byとsummariseという関数によって実現できます.
①クラスごとにデータフレームを分割する.= group_by
②分割したデータフレームごとに身長を平均する.= summarise
を使用することで簡単に処理することができます.
イメージはこんな感じです.
これをRで書くと,このようになります.
1 2 3 4 |
# classでグルーピングしてheightの平均を求める df %>% group_by(class) %>% summarise(mean = mean(height)) |
1 2 3 4 5 6 7 |
`summarise()` ungrouping output (override with `.groups` argument) # A tibble: 3 x 2 class mean <chr> <dbl> 1 a 162. 2 b 164 3 c 178. |
うまくできましたね.
これがgroup_byの基本になります.
2.グルーピングの条件
先ほどはクラスをキーにしてグルーピングしましたが,グルーピングの条件は,2つ以上でもOKです.
例えば,クラスの男女別で身長の平均が知りたい場合は,以下のようにすればいいです.
1 2 3 4 |
# classとgenderでグルーピングしてheightの平均を求める df %>% group_by(class, gender) %>% summarise(mean = mean(height)) |
1 2 3 4 5 6 7 8 9 10 11 |
`summarise()` regrouping output by 'class' (override with `.groups` argument) # A tibble: 6 x 3 # Groups: class [3] class gender mean <chr> <chr> <dbl> 1 a F 163. 2 a M 162 3 b F 150 4 b M 171 5 c F 168 6 c M 182 |
1 |
クラスと性別の組み合わせは全部で6種類あるので,6行のデータフレームが出力されています. このような感じで,グルーピングしたい条件は単数でも複数でもOKです.
出力されたデータフレームをよく見ると# Groups: class [3]となっていますね. 実は,データフレームは,classでグルーピングされた状態で出力されます. 複数条件でgroup_byをして,summarizeすると,複数条件 - 1の条件で出力されるんですね. 今回の例でいうとclass, genderでグルーピングしていたので,出力されるデータフレームはgenderが取れてclassでグルーピングされた状態で出力されます. なんてややこしい... これを解除するには,以下のようにungroupを使用すればOKです.
1 2 3 4 5 |
# ungroupでグルーピング解除 df %>% group_by(class, gender) %>% summarise(mean = mean(height)) %>% ungroup() |
1 2 3 4 5 6 7 8 9 10 |
`summarise()` regrouping output by 'class' (override with `.groups` argument) # A tibble: 6 x 3 class gender mean <chr> <chr> <dbl> 1 a F 163. 2 a M 162 3 b F 150 4 b M 171 5 c F 168 6 c M 182 |
グルーピングされているデータフレームとされていないデータフレームでは挙動が違うため,想定外のことが起こってしまう可能性があります.
細かいところなのですが,時々これでミスることがあるので念のため補足しました.
3.集計関数
先ほどはクラスごとの平均を計算しました.
もちろん,平均以外を算出することが可能です.
summariseでは,集計関数とよばれる基本統計量を算出する関数を主に使用します.
もちろんこれ以外も使えるのですが,95%くらいはこれらの関数を使用しています.
まずはこれらをマスターしましょう.
それでは,先ほどのデータを使用して,基本統計量を算出してみましょう.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 基本統計量の算出 df %>% group_by(class) %>% summarise( Max = max(height), Q3 = quantile(height, 0.75), Mean = mean(height), Median = median(height), Q1 = quantile(height, 0.25), Min = min(height), sd = sd(height), n = n() ) |
1 2 3 4 5 6 7 |
`summarise()` ungrouping output (override with `.groups` argument) # A tibble: 3 x 9 class Max Q3 Mean Median Q1 Min sd n <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int> 1 a 172 164. 162. 162 160 154 7.37 4 2 b 182 171 164 160 155 150 16.4 3 3 c 198 181. 178. 174 172. 168 13.3 4 |
ちゃんと出力されました.
指定した列名にNAがあるとエラーが出てしまいます
NAがあるときにそれを除いて,算出したい場合は,関数のオプションにna.rm = TRUEを付け加えればOKです.
1 2 3 4 |
# na.rm = TRUEとすると,NAを取り除いて算出 df %>% group_by(class) %>% summarise(Mean = mean(height, na.rm = TRUE)) |
まとめ
今回はグルーピングについて学習しました.
①条件ごとにデータフレームを分割する.= group_by
②分割したデータフレームごとに計算する.= summarise
とすることで,グルーピングしたグループごとに計算ができます.
計算に使用する関数は主に基本統計量(平均,標準偏差など)を算出するものです.
それじゃ,お疲れさまでした!!