このページに対応するRmdファイル:GitHub

1 Packages in R

パッケージには大別すると次の3種類がある:

  1. Rをインストールした時に自動的にインストールされており,Rを起動したときにデフォルトで使えるように設定されているもの(base::c, utils::str, etc.)
  2. Rをインストールした時に自動的にインストールされているが,Rを起動したときにデフォルトでは読み込まれていないもの(MASS::Boston, Matrix::Cholesky, etc.)
    • library(パッケージ名) で読み込んで 関数名 で呼び出すか,パッケージを読み込まずに パッケージ名::関数名 で呼び出す
  3. ユーザーが自分でインストールしなければ使えないもの(tidyverse, data.table, etc.)
    • install.packages("パッケージ名") でインストールし(最初の一度だけ実行),library(パッケージ名) で読み込む(Rを起動する度に実行)
    • Rstudio で install.packages が使えない場合,PC がインターネットに接続されていることを確認したうえで,CRAN レポジトリを変更してリトライ:Tools > Global Options > Packages > Primary CRAN repository を 「Japan (Tokyo)」 などに変更(参考:Setting CRAN repository options

補足:同じ名前の関数が複数のパッケージで使用されている場合があるので,常に パッケージ名::関数名 の形式でパッケージを指定するのを好む人もいる.

1.1 tidyverse package

データの整理・操作は tidyverse というパッケージに含まれる関数を使うのが一般的.

  • 正確には,tidyversedplyr (読み方:“dee-ply-er”) や ggplot2 などの複数のパッケージを束ねたもの
  • tidyverse をインストール/ロードすれば dplyrggplot2 などが同時にインストール/ロードされる

パッケージのインストールは R のインストール後に一度だけ実行する.

install.packages("tidyverse")  # run for the first time only

インストール後に R に読み込む. こちらはパッケージのインストールと異なり,R (または RStudio)を起動するたびに実行する.

library(tidyverse)

1.1.1 dplyr package

データのハンドリング(または data wrangling)を行うパッケージ.

  • filter … 条件に合致する行を抽出
  • select … 条件に合致する列(変数)を抽出
  • mutate … 新しい列(変数)を作成
  • rename … 列(変数)の名前を変更
  • left_join … 2つのデータセットを統合
  • summarise … データを要約
  • group_by … 行をグルーピング
    • Note: group_by はそれ単体で使われるわけではなく,通常は summarise 関数と併用される

これらの関数は %>% で表される「パイプ」と呼ばれる演算子と組み合わせて利用されることが多い. このパイプは tidyverse パッケージ群を構成するパッケージの一つ magrittr によって提供されているが,この授業では細かいことを理解する必要はない.

1.1.2 ggplot2 package

データ可視化のためのパッケージ. plot のようなデフォルトで使える関数と比べて文法に癖があるが,慣れれば論文に使える程度に綺麗な図を出力できる.

plot 関数はこれ単体でグラフを描画してくれるが,ggplot2 パッケージを使用する場合は ggplot 関数でデータと属性(X軸の変数,Y軸の変数,色に対応する変数,サイズに対応する変数)を指定し,次いで geom_xxx 関数でジオメトリ(点,線,棒,etc.)を指定するという2段階で描画する.

詳細は Kabacoff (2024) Modern Data Visualization with R などを参照.

2 Example of The Beatles data frame

2.1 Create “tibble” object

data.frame で作成したデータフレームのオブジェクトよりも少し扱いやすいデータフレーム型オブジェクトを tibble::tibble 関数で作成できる.

beatles <- tibble::tibble(
  name = c("John", "Paul", "George", "Ringo"), 
  born = c(1940, 1942, 1943, 1940),
  decease = c(1980, NA, NA, NA), 
  height = c(179, 180, 178, 170)
  )
beatles
## # A tibble: 4 × 4
##   name    born decease height
##   <chr>  <dbl>   <dbl>  <dbl>
## 1 John    1940    1980    179
## 2 Paul    1942      NA    180
## 3 George  1943      NA    178
## 4 Ringo   1940      NA    170

2.2 Pipe %>%

tidyverse スタイルのデータハンドリングでは「パイプ(演算子)」と呼ばれるものが用いられる.

%>% (大なり記号をパーセント記号で挟んだもの)がパイプと呼ばれる.

data %>% function」の形で使用し,パイプの前にある data をパイプの後の関数に渡す機能を持つ.

  • x %>% f()f(x) と(概ね)同じ.デフォルトでは関数の第一引数に渡す.
  • x %>% f(z)f(x, z) と(概ね)同じ.
  • z %>% f(x, .)f(x, z) と(概ね)同じ.第一引数以外の引数に渡す際は . を使う.
mean(x = 1:2)  # これまでの書き方.mean(c(1, 2)) と同じ
## [1] 1.5
1:2 %>% mean(x = .)  # "." でデータを受ける
## [1] 1.5
1:2 %>% mean()  # . が1つ目の引数なら省略可
## [1] 1.5
1:2 %>% mean  # () も省略可
## [1] 1.5
c(1, 2, NA) %>% mean(na.rm = TRUE)  # option も指定可
## [1] 1.5

逐次的な処理をパイプを用いて表現することができる.

sd(1:2)
## [1] 0.7071068
round(sd(1:2), 2)
## [1] 0.71
1:2 %>% sd %>% round(2)
## [1] 0.71

以下のようにネストが深い場合はパイプを使うことで処理の順序が理解しやすくなる.

\[ \frac{1}{n} \sum_i \log_{10} \sqrt{ |x_i| } \quad \mbox{を小数第2位まで表示} \]

round(mean(log(sqrt(abs(rnorm(n = 1000, mean = 1))), base = 10), na.rm = TRUE), 2)
## [1] -0.05
rnorm(n = 1000, mean = 1) %>% abs %>% sqrt %>% log(base = 10) %>% mean(na.rm = TRUE) %>% round(2)
## [1] -0.05

要するに,パイプを使う目的は,全く新しい種類の計算をすることではなく,既存の計算処理を順序通りに記述する(パイプライン処理する)ことにある.

  • コードの可読性が高まることで保守・デバッグが容易になるのに加え,計算内容を第三者が検証するうえでも役立つ.
  • このアイデアはR特有ではなく,UNIXのパイプなど先行する機能に着想を得て実装されたものと思われる.
  • パイプは tidyverse で提供される関数と組み合わせて以下のサブセクションのように使われることが一般的.

2.3 filter

残す行(observation)の条件を指定する.

beatles %>% filter(born >= 1941)  # 一般的な書き方
## # A tibble: 2 × 4
##   name    born decease height
##   <chr>  <dbl>   <dbl>  <dbl>
## 1 Paul    1942      NA    180
## 2 George  1943      NA    178
filter(beatles, born >= 1941)  # 計算結果は同じ
## # A tibble: 2 × 4
##   name    born decease height
##   <chr>  <dbl>   <dbl>  <dbl>
## 1 Paul    1942      NA    180
## 2 George  1943      NA    178
beatles[beatles$born >= 1941, ]  # もちろんこれも同じ
## # A tibble: 2 × 4
##   name    born decease height
##   <chr>  <dbl>   <dbl>  <dbl>
## 1 Paul    1942      NA    180
## 2 George  1943      NA    178

filter を適用した後のデータセットを新しいオブジェクトに割り当てるには <- を用いる(上書きも可;以下同様).

beatles_ver2 <- beatles %>% filter(born >= 1941)
beatles_ver2
## # A tibble: 2 × 4
##   name    born decease height
##   <chr>  <dbl>   <dbl>  <dbl>
## 1 Paul    1942      NA    180
## 2 George  1943      NA    178

複数の条件を指定することもできる.

beatles %>% filter(born >= 1941 & height < 180)
## # A tibble: 1 × 4
##   name    born decease height
##   <chr>  <dbl>   <dbl>  <dbl>
## 1 George  1943      NA    178

2.4 select

残す列(変数)の名前を指定する.

beatles %>% select(name)
## # A tibble: 4 × 1
##   name  
##   <chr> 
## 1 John  
## 2 Paul  
## 3 George
## 4 Ringo
beatles %>% select(name, born)
## # A tibble: 4 × 2
##   name    born
##   <chr>  <dbl>
## 1 John    1940
## 2 Paul    1942
## 3 George  1943
## 4 Ringo   1940

マイナス記号 - を使って「-変数名」と指定すると当該変数以外が残る.

beatles %>% select(-height)
## # A tibble: 4 × 3
##   name    born decease
##   <chr>  <dbl>   <dbl>
## 1 John    1940    1980
## 2 Paul    1942      NA
## 3 George  1943      NA
## 4 Ringo   1940      NA

2.5 mutate

新しく列(変数)を作成する.

beatles %>% mutate(primary_role = c("vocal", "vocal", "guitar", "drum"))
## # A tibble: 4 × 5
##   name    born decease height primary_role
##   <chr>  <dbl>   <dbl>  <dbl> <chr>       
## 1 John    1940    1980    179 vocal       
## 2 Paul    1942      NA    180 vocal       
## 3 George  1943      NA    178 guitar      
## 4 Ringo   1940      NA    170 drum

既存の変数を利用して新しい変数を作成することもできる.

beatles %>% mutate(age_at_debut = 1962 - born)
## # A tibble: 4 × 5
##   name    born decease height age_at_debut
##   <chr>  <dbl>   <dbl>  <dbl>        <dbl>
## 1 John    1940    1980    179           22
## 2 Paul    1942      NA    180           20
## 3 George  1943      NA    178           19
## 4 Ringo   1940      NA    170           22

2.6 rename

列(変数)の名前を変える.

beatles %>% rename(birth_year = born)
## # A tibble: 4 × 4
##   name   birth_year decease height
##   <chr>       <dbl>   <dbl>  <dbl>
## 1 John         1940    1980    179
## 2 Paul         1942      NA    180
## 3 George       1943      NA    178
## 4 Ringo        1940      NA    170

2.7 left_join

別のデータセットと統合する.

beatles_primary_role <- tibble::tibble(name = c("John", "Paul", "George", "Ringo"), 
                                       primary_role = c("vocal", "vocal", "guitar", "drum"))
beatles_primary_role
## # A tibble: 4 × 2
##   name   primary_role
##   <chr>  <chr>       
## 1 John   vocal       
## 2 Paul   vocal       
## 3 George guitar      
## 4 Ringo  drum
beatles %>% left_join(beatles_primary_role, by = "name")
## # A tibble: 4 × 5
##   name    born decease height primary_role
##   <chr>  <dbl>   <dbl>  <dbl> <chr>       
## 1 John    1940    1980    179 vocal       
## 2 Paul    1942      NA    180 vocal       
## 3 George  1943      NA    178 guitar      
## 4 Ringo   1940      NA    170 drum

2.7.1 If either data frame contains NA / いずれかのデータフレームに欠損値がある場合

一方のデータフレームにしかない行がある場合,主たるデータフレーム(マージされる側)の行はそのまま残る.

補足:コードの文法上左側にあるデータセットに合わせてマージするので left_join という関数名が使われている.右側に合わせる場合は right_join,積集合でマージするのは inner_join,和集合でマージするのは full_join

Case 1. 担当楽器のデータセットに欠損がある場合.

beatles_primary_role_wo_paul <- tibble::tibble(name = c("John", "George", "Ringo"), 
                                               primary_role = c("vocal", "guitar", "drum"))
beatles_primary_role_wo_paul
## # A tibble: 3 × 2
##   name   primary_role
##   <chr>  <chr>       
## 1 John   vocal       
## 2 George guitar      
## 3 Ringo  drum
beatles %>% left_join(beatles_primary_role_wo_paul, by = "name")
## # A tibble: 4 × 5
##   name    born decease height primary_role
##   <chr>  <dbl>   <dbl>  <dbl> <chr>       
## 1 John    1940    1980    179 vocal       
## 2 Paul    1942      NA    180 <NA>        
## 3 George  1943      NA    178 guitar      
## 4 Ringo   1940      NA    170 drum

Case 2. 逆に,主なデータフレームの方に欠損がある場合.

beatles %>% 
  filter(name != "Paul") %>% 
  left_join(beatles_primary_role, by = "name")
## # A tibble: 3 × 5
##   name    born decease height primary_role
##   <chr>  <dbl>   <dbl>  <dbl> <chr>       
## 1 John    1940    1980    179 vocal       
## 2 George  1943      NA    178 guitar      
## 3 Ringo   1940      NA    170 drum

2.8 summarise

データを要約する.

beatles %>% summarise(mean_height = mean(height), 
                      std_dev_height = sd(height),
                      sample_size = n())
## # A tibble: 1 × 3
##   mean_height std_dev_height sample_size
##         <dbl>          <dbl>       <int>
## 1        177.           4.57           4

2.9 group_by

summarise 関数と組み合わせて使うことで,グループごとの要約統計量を計算したり何らかの統計処理を行うことができる.

beatles %>% 
  group_by(born) %>% 
  summarise(mean_height = mean(height), 
            std_dev_height = sd(height),
            sample_size = n())
## # A tibble: 3 × 4
##    born mean_height std_dev_height sample_size
##   <dbl>       <dbl>          <dbl>       <int>
## 1  1940        174.           6.36           2
## 2  1942        180           NA              1
## 3  1943        178           NA              1

2.10 Scatter plot

まずは ggplot だけ実行してみる. データが何も描かれていないキャンバスだけが表示される.

ggplot(data = beatles, mapping = aes(x = born, y = height))

ここに点のレイヤーを geom_point 関数で追加する.

ggplot(data = beatles, mapping = aes(x = born, y = height)) + 
  geom_point()

軸のラベルを変更する.

ggplot(data = beatles, mapping = aes(x = born, y = height)) + 
  geom_point() + 
  xlab("Year of birth")

キャンバスのテーマを変える.

ggplot(data = beatles, mapping = aes(x = born, y = height)) + 
  geom_point() + 
  theme_classic()

3 Example of Titanic data

titanic <- read.csv("https://raw.githubusercontent.com/kurodaecon/bs/main/data/titanic3_csv.csv")

3.1 filter

titanic %>% filter(age > 75)
##   pclass survived    sex age sibsp parch  fare embarked
## 1      1        1   male  80     0     0 30.00        S
## 2      1        1 female  76     1     0 78.85        S

3.2 group_by and summarise

性別ごとの生存率.

titanic %>% 
  group_by(sex) %>%
  summarise(survival_rate = mean(survived), 
            sample_size = n())
## # A tibble: 2 × 3
##   sex    survival_rate sample_size
##   <chr>          <dbl>       <int>
## 1 female         0.727         466
## 2 male           0.191         843

性別と客室等級ごとの生存率.

titanic %>% 
  group_by(sex, pclass) %>%
  summarise(survival_rate = mean(survived), 
            sample_size = n())
## # A tibble: 6 × 4
## # Groups:   sex [2]
##   sex    pclass survival_rate sample_size
##   <chr>   <int>         <dbl>       <int>
## 1 female      1         0.965         144
## 2 female      2         0.887         106
## 3 female      3         0.491         216
## 4 male        1         0.341         179
## 5 male        2         0.146         171
## 6 male        3         0.152         493

性別と年齢層ごとの生存率.

titanic %>% 
  mutate(age_group = cut(age, breaks = c(0, 20, 60, 100), right = FALSE)) %>% 
  group_by(sex, age_group) %>%
  summarise(survival_rate = mean(survived), 
            sample_size = n())
## # A tibble: 8 × 4
## # Groups:   sex [2]
##   sex    age_group survival_rate sample_size
##   <chr>  <fct>             <dbl>       <int>
## 1 female [0,20)            0.699         103
## 2 female [20,60)           0.770         274
## 3 female [60,100)          0.818          11
## 4 female <NA>              0.603          78
## 5 male   [0,20)            0.279         122
## 6 male   [20,60)           0.193         507
## 7 male   [60,100)          0.103          29
## 8 male   <NA>              0.141         185

性別と客室等級と年齢層ごとの生存率.

titanic %>% 
  mutate(age_group = cut(age, breaks = c(0, 20, 60, 100), right = FALSE)) %>% 
  group_by(sex, pclass, age_group) %>%
  summarise(survival_rate = mean(survived), 
            sample_size = n()) 
## # A tibble: 24 × 5
## # Groups:   sex, pclass [6]
##    sex    pclass age_group survival_rate sample_size
##    <chr>   <int> <fct>             <dbl>       <int>
##  1 female      1 [0,20)            0.938          16
##  2 female      1 [20,60)           0.972         108
##  3 female      1 [60,100)          0.889           9
##  4 female      1 <NA>              1              11
##  5 female      2 [0,20)            0.958          24
##  6 female      2 [20,60)           0.885          78
##  7 female      2 [60,100)          0               1
##  8 female      2 <NA>              0.667           3
##  9 female      3 [0,20)            0.540          63
## 10 female      3 [20,60)           0.420          88
## # ℹ 14 more rows

カテゴリー数が多いためにすべて表示されていない. 以下のように表示数を調整できる.

titanic %>% 
  mutate(age_group = cut(age, breaks = c(0, 20, 60, 100), right = FALSE)) %>% 
  group_by(sex, pclass, age_group) %>%
  summarise(survival_rate = mean(survived), 
            sample_size = n()) %>% 
  print(n = 30)
## # A tibble: 24 × 5
## # Groups:   sex, pclass [6]
##    sex    pclass age_group survival_rate sample_size
##    <chr>   <int> <fct>             <dbl>       <int>
##  1 female      1 [0,20)           0.938           16
##  2 female      1 [20,60)          0.972          108
##  3 female      1 [60,100)         0.889            9
##  4 female      1 <NA>             1               11
##  5 female      2 [0,20)           0.958           24
##  6 female      2 [20,60)          0.885           78
##  7 female      2 [60,100)         0                1
##  8 female      2 <NA>             0.667            3
##  9 female      3 [0,20)           0.540           63
## 10 female      3 [20,60)          0.420           88
## 11 female      3 [60,100)         1                1
## 12 female      3 <NA>             0.531           64
## 13 male        1 [0,20)           0.6             10
## 14 male        1 [20,60)          0.363          124
## 15 male        1 [60,100)         0.118           17
## 16 male        1 <NA>             0.286           28
## 17 male        2 [0,20)           0.444           27
## 18 male        2 [20,60)          0.0806         124
## 19 male        2 [60,100)         0.143            7
## 20 male        2 <NA>             0.154           13
## 21 male        3 [0,20)           0.188           85
## 22 male        3 [20,60)          0.166          259
## 23 male        3 [60,100)         0                5
## 24 male        3 <NA>             0.111          144

年齢の平均を計算しようとすると NA が返ってくる.

titanic %>% 
  summarise(age_mean = mean(age))
##   age_mean
## 1       NA

これは年齢変数 ageNA が含まれるため. na.rm = TRUE 引数を追加する.

titanic %>% 
  summarise(age_mean = mean(age, na.rm = TRUE))
##   age_mean
## 1 29.88114

3.3 Correlation matrix

相関係数行列.

titanic %>% 
  select(age, fare, parch) %>% 
  cor(use = "complete.obs")
##              age      fare      parch
## age    1.0000000 0.1787399 -0.1502409
## fare   0.1787399 1.0000000  0.2167232
## parch -0.1502409 0.2167232  1.0000000

3.4 Histogram using ggplot2

年齢.

ggplot(data = titanic, mapping = aes(x = age)) + 
  geom_histogram()

性別ごとに分ける.

ggplot(data = titanic, mapping = aes(x = age, fill = sex)) + 
  geom_histogram(position = "dodge") + 
  scale_fill_grey() +  # grey scale 
  theme_classic()

3.5 Bar plot using ggplot2

出港地ごとの人数.

titanic %>% 
  filter(embarked != "") %>% 
  group_by(embarked) %>% 
  summarise(person = n()) %>% 
  ggplot(mapping = aes(x = embarked, y = person)) + 
  geom_bar(stat = "identity") + 
  theme_classic()

性別ごとに分ける. ついでにX軸のラベルも修正しておく.

titanic %>% 
  filter(embarked != "") %>% 
  group_by(embarked, sex) %>% 
  summarise(person = n()) %>% 
  ggplot(mapping = aes(x = embarked, y = person, fill = sex)) + 
  geom_bar(stat = "identity", position = "dodge") + 
  scale_x_discrete(labels = c("Cherbourg", "Queenstown", "Southampton")) + 
  scale_fill_grey() + 
  theme_classic()

3.6 Pie chart using ggplot2

出港地ごとの人数.

titanic %>% 
  filter(embarked != "") %>% 
  group_by(embarked) %>% 
  summarise(person = n()) %>% 
  ggplot(mapping = aes(x = "x", y = person, fill = embarked)) + 
  geom_bar(stat = "identity", position = "stack") + 
  coord_polar(theta = "y") + 
  scale_fill_brewer(labels = c("Cherbourg", "Queenstown", "Southampton")) + 
  theme_classic()

3.7 Boxplot using ggplot2

性別ごとの年齢.

ggplot(data = titanic, mapping = aes(x = sex, y = age)) + 
  geom_boxplot()

性別・客室等級ごとの年齢.

ggplot(data = titanic, mapping = aes(x = sex, y = age, fill = factor(pclass))) + 
  geom_boxplot() + 
  scale_fill_grey(start = 0.4, end = 0.9) + 
  theme_classic()

データの分布が複雑な場合(多峰など),バイオリンプロットという選択肢がある.

ggplot(data = titanic, mapping = aes(x = sex, y = age)) + 
  geom_violin()

3.8 Scatter plot using ggplot2

ビートルズやSwissデータと同様に散布図を描き,スムージング曲線を追加する.

点同士が重なってしまうため geom_jitter 関数でY軸方向にばらつかせて描画.

ggplot(data = titanic, mapping = aes(x = age, y = survived)) + 
  geom_point() + 
  geom_jitter(height = .05, width = 0) + 
  geom_smooth() 

Y軸の survived は 0/1 の binary 変数なので jitter は違和感がある. Binned plot はよい代替案だろう.

ggplot(data = titanic, mapping = aes(x = age, y = survived)) + 
  stat_summary_bin()

性別による死亡率の違いを示す.

ggplot(data = titanic, mapping = aes(x = age, y = survived, color = sex, shape = sex, linetype = sex)) + 
  geom_point(size = 0.5) + 
  geom_jitter(height = .05, width = 0) + 
  geom_smooth(se = FALSE) + 
  scale_color_brewer(palette = "Dark2") + # colorblind-friendly palette 
  theme_classic()

50歳代からサンプルサイズが大きく低下するため,フィッティングの曲線は参考にならない点に注意.

客室等級による死亡率の違いを示す.

  • pclass は連続変数なので factor 関数で因子型の変数に変換して使う.
ggplot(data = titanic, mapping = aes(x = age, y = survived, color = factor(pclass), 
                                     shape = factor(pclass), linetype = factor(pclass))) + 
  geom_point() + 
  geom_jitter(height = .05, width = 0) + 
  geom_smooth(se = FALSE) + 
  scale_color_brewer(palette = "Dark2") +
  theme_classic()

4 Pipe in base R

Base R (Rインストール時にbuilt-inされている標準パッケージのみを使用し,追加のパッケージを手動でインストールしない状態)でも pipe が使える.

  • これは比較的新しい機能.tidyverse スタイルの %>% を用いたデータハンドリングが普及したことを受けて2021年頃に実装された.
  • Base R の pipe は |> と書く.

4.1 Pipe |>

|>%>% と同様に直前の値を関数の第一引数に渡す.

1:2 |> mean(x = _)  # "_" でデータを受ける
## [1] 1.5
1:2 |> mean()  # _ が1つ目の引数なら省略可(注:カッコは省略不可)
## [1] 1.5
c(1, 2, NA) |> mean(na.rm = TRUE)  # option も指定可
## [1] 1.5
titanic |> head(2)
##   pclass survived    sex   age sibsp parch     fare embarked
## 1      1        1 female 29.00     0     0 211.3375        S
## 2      1        1   male  0.92     1     2 151.5500        S
titanic[, c("survived", "age")] |> cor(use = "complete.obs") |> round(2)
##          survived   age
## survived     1.00 -0.06
## age         -0.06  1.00

4.2 subset corresponding to filter

titanic %>% filter(age >= 75)
##   pclass survived    sex age sibsp parch  fare embarked
## 1      1        1   male  80     0     0 30.00        S
## 2      1        1 female  76     1     0 78.85        S
titanic |> subset(age >= 75)
##    pclass survived    sex age sibsp parch  fare embarked
## 15      1        1   male  80     0     0 30.00        S
## 62      1        1 female  76     1     0 78.85        S

4.3 transform corresponding to mutate

titanic %>% mutate(family = sibsp + parch) %>% head(2)
##   pclass survived    sex   age sibsp parch     fare embarked family
## 1      1        1 female 29.00     0     0 211.3375        S      0
## 2      1        1   male  0.92     1     2 151.5500        S      3
titanic |> transform(family = sibsp + parch) |> head(2)
##   pclass survived    sex   age sibsp parch     fare embarked family
## 1      1        1 female 29.00     0     0 211.3375        S      0
## 2      1        1   male  0.92     1     2 151.5500        S      3

4.4 aggregate corresponding to group_by + summarise

titanic %>% group_by(pclass) %>% summarise(survived_rate = mean(survived))
## # A tibble: 3 × 2
##   pclass survived_rate
##    <int>         <dbl>
## 1      1         0.619
## 2      2         0.430
## 3      3         0.255
titanic |> aggregate(survived ~ pclass, data = _, FUN = mean)
##   pclass  survived
## 1      1 0.6191950
## 2      2 0.4296029
## 3      3 0.2552891

注:上記の対比だけを見ると tidyverse スタイルのデータ処理が不要であるかのように見えるかもしれないが,実際にはそんなことはない. 上記のような単純な処理であれば Base R の標準的な関数だけでも事足りる場合もあるが,複雑な処理をする上では tidyverse を使った方がよい.