180  group_by関数の使い方の例

library(tidyverse)

それでは、group_by関数の使い方について解説していきます。

利用するデータは、

{
  set.seed(12345)
  dat <- tibble(
    q1 = sample(letters[1:3],100,replace = TRUE),
    q2 = sample(letters[1:3],100,replace = TRUE),
    q3 = sample(letters[1:3],100,replace = TRUE),
    q4 = sample(letters[1:3],100,replace = TRUE),
    q5 = sample(letters[1:3],100,replace = TRUE)
  )
  write_excel_csv(dat,"data/practice_group_by.csv")  
}

dat <- read_csv("data/practice_group_by.csv")
Rows: 100 Columns: 5
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (5): q1, q2, q3, q4, q5

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

こんなデータです。

まず例えば、q1変数での解答はそれぞれ何件あるかを確認するには、

dat %>% 
  group_by(q1) %>% 
  summarise(n = n())
# A tibble: 3 × 2
  q1        n
  <chr> <int>
1 a        27
2 b        35
3 c        38

としてあげることで、q1でグループ化してsummariseで数を数えることができました

おなじように、q1とq2の変数の組み合わせが何件あるのかを確認するには、

ex2 <- dat %>% 
  group_by(q1,q2) %>% 
  summarise(n = n())
`summarise()` has grouped output by 'q1'. You can override using the `.groups`
argument.
ex2
# A tibble: 9 × 3
# Groups:   q1 [3]
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

このように、group_byに二つの変数を入れるとOKです。ただ、注意が必要なのは、Summariseをすると、groupの指定が「1段階解除される」という仕組みになっており、ex2データのグループは、q1のみとなっています。

グループが残っていると、おもわぬ動作が生じることがあります

例えば、

ex2 %>% select(!q1)
Adding missing grouping variables: `q1`
# A tibble: 9 × 3
# Groups:   q1 [3]
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

と、ex2からq1変数を除去しようとしても、groupに利用されている変数は除去できず、もとにもどってしまいます。なので、グループ集計等、グループである必然性がないデータについては、

ex3 <- ex2 %>% ungroup()

ex3
# A tibble: 9 × 3
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

このように、ungroup()関数を用いてグループを解除しておくか、

dat %>% 
  group_by(q1,q2) %>% 
  summarise(n = n(), .groups="drop")
# A tibble: 9 × 3
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

このように.groups=“drop”という設定をしておくと、自動的にグループ化が解除された形でデータが帰ってきます。

注意:この.groups=dropという仕様は、この動画を作成時点で実験的な試みらしいので、将来的には動作が変更される可能性があります。

なので、個人的にはungroup()で明示的にグループ解除を必要がなくなったら行う癖付けをしておくほうがよいように思っています。

(1つの関数で色々な処理をするよりも、1関数、1処理でシンプルに書いておく方が分かりやすい気がします。)

さて、ここまでの例では、組み合わせを含めて数を数えるという方法を解説してきました

ex3
# A tibble: 9 × 3
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

ただ、実は、この処理をもっと簡単に書く方法がり、

dat %>% count(q1,q2)
# A tibble: 9 × 3
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

このように、count関数を利用しましよう。

?count
starting httpd help server ... done

をみても、ほぼ同じ処理であると書いてありますね。

次にgroup_byとmutateを組み合わせてみましょう。

dat2 <- dat %>% 
  count(q1,q2)

dat2
# A tibble: 9 × 3
  q1    q2        n
  <chr> <chr> <int>
1 a     a         7
2 a     b        10
3 a     c        10
4 b     a         7
5 b     b        12
6 b     c        16
7 c     a        15
8 c     b        13
9 c     c        10

このように集計されたデータに対して、

例えば、q1=aの中で、q2=aが占める割合等を計算したいときに、

dat2 %>% 
  group_by(q1) %>% 
  mutate(nq1 = sum(n))
# A tibble: 9 × 4
# Groups:   q1 [3]
  q1    q2        n   nq1
  <chr> <chr> <int> <int>
1 a     a         7    27
2 a     b        10    27
3 a     c        10    27
4 b     a         7    35
5 b     b        12    35
6 b     c        16    35
7 c     a        15    38
8 c     b        13    38
9 c     c        10    38

このように書いてあげると、q1という集団毎のsum(n)の値を入れた列を新たに作成することができます。

dat2 %>% 
  #group_by(q1) %>% 
  mutate(nq1 = sum(n))
# A tibble: 9 × 4
  q1    q2        n   nq1
  <chr> <chr> <int> <int>
1 a     a         7   100
2 a     b        10   100
3 a     c        10   100
4 b     a         7   100
5 b     b        12   100
6 b     c        16   100
7 c     a        15   100
8 c     b        13   100
9 c     c        10   100

このように,group_byがない場合は、単純にn列の全ての数字を足した値が繰り返してnq1列に挿入されますが、

dat2 %>% 
  group_by(q1) %>% 
  mutate(nq1 = sum(n))
# A tibble: 9 × 4
# Groups:   q1 [3]
  q1    q2        n   nq1
  <chr> <chr> <int> <int>
1 a     a         7    27
2 a     b        10    27
3 a     c        10    27
4 b     a         7    35
5 b     b        12    35
6 b     c        16    35
7 c     a        15    38
8 c     b        13    38
9 c     c        10    38

グループ化してあげると、q1のグループ毎に集計された値がnq1に含まれます。ここでも、group_byでデータに線が入って分割された別々の表で処理が行われているとイメージがあると、mutateの動作も理解できるのではないでしょうか?

次の動画からはデータの処理でよく遭遇する「差の計算」について解説していきます