6 要約値を作る:summarise
- 本章のポイント
- パッケージdplyrの関数summarise()
- 結果をデータフレームとして出力するため,扱いが便利
- データを知るうえで要約作業は頻繁に行うことが想定される
- 便利な要約パッケージが色々あるものの,summarise()は柔軟な出力が可能なので使いこなせると役に立つ
 
- パッケージ
6.1 基本
- 
summarise()の中に出力したい変数名を書き,=の後に計算する関数を入れる
- 例:bill_length_mmの平均値を算出する
- データは2.1で読み込んだdfを使用
# まだtidyverseパッケージを読み込んでない場合は以下の#を外して実行
# library(tidyverse)
df |> 
  summarise(blm_平均値 = mean(bill_length_mm, na.rm = TRUE))## # A tibble: 1 × 1
##   blm_平均値
##        <dbl>
## 1       43.96.2 複数の計算
- 複数の変数について平均値と標準偏差(SD)と人数(n)を出したいときは,基本知識では全部書くので長くなる
- SDはsd()関数,nは変数内の欠損のない行以外の数の合計で算出
- 
sum(!is.na(.x))は,NAのない行の数を総計するので,平均値やSDの計算に用いた人数を取得できる
 
- SDは
df |> 
  summarise(blm_mean = mean(bill_length_mm, na.rm = TRUE),
            bdm_mean = mean(bill_depth_mm, na.rm = TRUE),
            blm_sd = sd(bill_length_mm, na.rm = TRUE),
            bdm_sd = sd(bill_depth_mm, na.rm = TRUE),
            blm_n  = sum(!is.na(bill_length_mm)),
            bdm_n  = sum(!is.na(bill_depth_mm)))## # A tibble: 1 × 6
##   blm_mean bdm_mean blm_sd bdm_sd blm_n bdm_n
##      <dbl>    <dbl>  <dbl>  <dbl> <int> <int>
## 1     43.9     17.2   5.46   1.97   342   3426.2.1 【効率化】
- 
5.3.2で出てきたacross()がここでも有用
- 
across()の第一引数に指定したい変数名ベクトル,またはヘルパー関数を入れる
- 実行したい関数を無名関数としてlist内に名前(これが接尾辞になる)をつけて列挙する
df |> 
  summarise(across(c(bill_length_mm, bill_depth_mm),
                   list(mean = \(x) mean(x, na.rm = TRUE),
                          sd = \(x)   sd(x, na.rm = TRUE),
                           n = \(x)  sum(!is.na(x)))))## # A tibble: 1 × 6
##   bill_length_mm_mean bill_length_mm_sd bill_length_mm_n
##                 <dbl>             <dbl>            <int>
## 1                43.9              5.46              342
## # ℹ 3 more variables: bill_depth_mm_mean <dbl>,
## #   bill_depth_mm_sd <dbl>, bill_depth_mm_n <int>
# purrr 1.0.0より前のバージョンでの書き方
# df |> 
#   summarise(across(c(bill_length_mm, bill_depth_mm),
#                    list(mean = ~mean(.x, na.rm = TRUE),
#                           sd = ~sd(.x, na.rm = TRUE),
#                            n = ~sum(!is.na(.x)))))- 
across()ではヘルパー関数が使える
df |> 
  summarise(across(starts_with("bill"),
                   list(mean = \(x) mean(x, na.rm = TRUE),
                          sd = \(x)   sd(x, na.rm = TRUE),
                           n = \(x)  sum(!is.na(x)))))## # A tibble: 1 × 6
##   bill_length_mm_mean bill_length_mm_sd bill_length_mm_n
##                 <dbl>             <dbl>            <int>
## 1                43.9              5.46              342
## # ℹ 3 more variables: bill_depth_mm_mean <dbl>,
## #   bill_depth_mm_sd <dbl>, bill_depth_mm_n <int>- 
list()内に関数を並べている部分は,関数を名前付きリストにしているだけなので,外に出して1回オブジェクトとして指定すれば記述がすっきりするし,後の同じ作業で繰り返し使える
# 関数のリストをオブジェクトfnlistに格納
fnlist <- 
  list(mean = \(x) mean(x, na.rm = TRUE),
         sd = \(x)   sd(x, na.rm = TRUE),
          n = \(x)  sum(!is.na(x)))
df |> 
  summarise(across(ends_with("mm"),
                   all_of(fnlist)))## # A tibble: 1 × 9
##   bill_length_mm_mean bill_length_mm_sd bill_length_mm_n
##                 <dbl>             <dbl>            <int>
## 1                43.9              5.46              342
## # ℹ 6 more variables: bill_depth_mm_mean <dbl>,
## #   bill_depth_mm_sd <dbl>, bill_depth_mm_n <int>,
## #   flipper_length_mm_mean <dbl>, flipper_length_mm_sd <dbl>,
## #   flipper_length_mm_n <int>6.2.2 【並び替え】
- 上記の出力は横に長いため見にくい
- 
tidyr::pivot_longer()で,データフレームの行列入れ替えができる
- 引数をnames_patternとnames_toを下記のように指定することで,変数の接尾辞を列名にできる
- 下記コードのsummarise()部分の構造は前のチャンクと変数名以外同じ
df |> 
  summarise(across(bill_length_mm:body_mass_g,
                   list(mean = \(x) mean(x, na.rm = TRUE),
                          sd = \(x)   sd(x, na.rm = TRUE),
                           n = \(x)  sum(!is.na(x))))) |> 
  pivot_longer(everything(),
               names_to = c("items", ".value"), # ".value"の部分を列名に
               names_pattern = "(.*)_(.*)")    # 正規表現## # A tibble: 4 × 4
##   items               mean     sd     n
##   <chr>              <dbl>  <dbl> <int>
## 1 bill_length_mm      43.9   5.46   342
## 2 bill_depth_mm       17.2   1.97   342
## 3 flipper_length_mm  201.   14.1    342
## 4 body_mass_g       4202.  802.     3426.2.3 [練習問題]
- dfデータの変数名に”length”を含む変数に対して平均値とSDとnを計算したデータフレームを作成して”res”オブジェクトに格納しよう
- 次に作成したデータフレームをpivot_longer()を使って見やすいように縦に変換しよう
6.3 層別(グループ別)集計
- 
group_by()にグループを表す変数を指定するとできる
df |> 
  group_by(species) |> 
  summarise(across(c(bill_length_mm, bill_depth_mm),
                   list(mean = \(x) mean(x, na.rm = TRUE),
                          sd = \(x)   sd(x, na.rm = TRUE))))## # A tibble: 3 × 5
##   species   bill_length_mm_mean bill_length_mm_sd
##   <fct>                   <dbl>             <dbl>
## 1 Adelie                   38.8              2.66
## 2 Chinstrap                48.8              3.34
## 3 Gentoo                   47.5              3.08
## # ℹ 2 more variables: bill_depth_mm_mean <dbl>,
## #   bill_depth_mm_sd <dbl>- グループを重ねることも可能
df |> 
  group_by(species, sex) |> 
  summarise(across(c(bill_length_mm, bill_depth_mm),
                   list(mean = \(x) mean(x, na.rm = TRUE),
                          sd = \(x)   sd(x, na.rm = TRUE))))## # A tibble: 8 × 6
## # Groups:   species [3]
##   species   sex    bill_length_mm_mean bill_length_mm_sd
##   <fct>     <fct>                <dbl>             <dbl>
## 1 Adelie    female                37.3              2.03
## 2 Adelie    male                  40.4              2.28
## 3 Adelie    <NA>                  37.8              2.80
## 4 Chinstrap female                46.6              3.11
## 5 Chinstrap male                  51.1              1.56
## 6 Gentoo    female                45.6              2.05
## 7 Gentoo    male                  49.5              2.72
## 8 Gentoo    <NA>                  45.6              1.37
## # ℹ 2 more variables: bill_depth_mm_mean <dbl>,
## #   bill_depth_mm_sd <dbl>6.4 【効率化】関数にする
- 関数作成の基本は(1.4.2.2参照)
6.4.1 複数変数の平均値とSDとnを計算する関数
- 「{{ }}」はcurly curlyと読み,関数を作成するときに,代入先の変数名の場所を指定する時などに活躍- 下記の例の場合,{{ }}を外すと動かない
 
- 下記の例の場合,
- 例:引数にデータフレーム(data)と変数(vars)を入れると平均値とSDとnを返す関数mean_sd_n()を定義
mean_sd_n <- function(data, vars){
  data |> 
    summarise(across({{vars}},
                     list(mean = \(x) mean(x, na.rm = TRUE),
                            sd = \(x) sd(x, na.rm = TRUE),
                             n = \(x) sum(!is.na(x)))))
}- ここで定義した関数mean_sd_n()に引数としてデータフレームと変数を入れると結果が表示される
mean_sd_n(df, bill_length_mm)## # A tibble: 1 × 3
##   bill_length_mm_mean bill_length_mm_sd bill_length_mm_n
##                 <dbl>             <dbl>            <int>
## 1                43.9              5.46              342- 引数varsの部分はacross()の第一引数に入れるものと同じ指定ができるため,変数ベクトルやヘルパー関数が入る
# 変数ベクトル
mean_sd_n(df, c(flipper_length_mm, body_mass_g))## # A tibble: 1 × 6
##   flipper_length_mm_mean flipper_length_mm_sd flipper_length_mm_n
##                    <dbl>                <dbl>               <int>
## 1                   201.                 14.1                 342
## # ℹ 3 more variables: body_mass_g_mean <dbl>,
## #   body_mass_g_sd <dbl>, body_mass_g_n <int>
# 文字でも可能
# mean_sd_n(df, c("flipper_length_mm", "body_mass_g"))
# ヘルパー関数
mean_sd_n(df, starts_with("bill"))## # A tibble: 1 × 6
##   bill_length_mm_mean bill_length_mm_sd bill_length_mm_n
##                 <dbl>             <dbl>            <int>
## 1                43.9              5.46              342
## # ℹ 3 more variables: bill_depth_mm_mean <dbl>,
## #   bill_depth_mm_sd <dbl>, bill_depth_mm_n <int>