データフレームを“直感的に整形する方法”(dplyr)を学ぶ。
本講では、まず前回学んだデータフレームの拡張形式であるtibbleについて学びます(ただし、見た目はほとんど変わりません)。
tibbleは、Rの従来のdata.frameを改良したデータ構造で、列の型が明示され、自動的な型変換も行われないため、安全で読みやすいデータ操作が可能になる。一方、dplyrは、このtibbleを標準的な入出力形式として設計されたデータ整形パッケージであり、行の抽出・列の選択・並べ替え・要約などを直感的な文法で記述できる。dplyrの関数は、data.frameを入力しても結果をtibbleとして返すため、両者を組み合わせることで、データの可読性と操作性が飛躍的に高まり、<-演算子を用いた処理の流れも明快になる。結果として、分析プロセスの再現性と保守性が大きく向上する。
library(tibble) または
library(tidyverse)
を読み込む必要がある# tibbleを使うための準備
library(tibble)
データフレームとtibbleで同じデータを入れます。
# data.frameとの比較(knit時:dfはbase出力/tibbleはtibble出力)
df <- data.frame(x = 1:3, y = c("A", "B", "C"))
tb <- tibble(x = 1:3, y = c("A", "B", "C"))
こちらがデータフレームの出力
print(df)
## x y ## 1 1 A ## 2 2 B ## 3 3 C
他方、tibbleには型の情報が標準で出力されます。
print(tb)
## # A tibble: 3 × 2 ## x y ## <int> <chr> ## 1 1 A ## 2 2 B ## 3 3 C
classを確認すると、 tibbleがデータフレーム形式を保持しつつ、 それを拡張したものであることがわかります。
class(df); class(tb) # 型の違いを確認
## [1] "data.frame"
## [1] "tbl_df" "tbl" "data.frame"
実際、tibbleでも、data.frameを引数とする関数がそのまま使えます。
# 行数、列数、# 次元
nrow(tb);ncol(tb); dim(tb)
## [1] 3
## [1] 2
## [1] 3 2
# 要約統計
summary(tb)
## x y ## Min. :1.0 Length:3 ## 1st Qu.:1.5 Class :character ## Median :2.0 Mode :character ## Mean :2.0 ## 3rd Qu.:2.5 ## Max. :3.0
# データフレームとして認識される
is.data.frame(tb)
## [1] TRUE
$、[[ ]]、pull()、select()slice()# tibbleを用意
people <- tibble(
name = c("A", "B", "C"),
height = c(165, 172, 180),
weight = c(55, 65, 80),
gender = c("F","M","M")
)
print(people)
## # A tibble: 3 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 A 165 55 F ## 2 B 172 65 M ## 3 C 180 80 M
# 各列を取り出す
people$name # $を使う(一般的)
## [1] "A" "B" "C"
people[["height"]] # [[ ]]で取り出す
## [1] 165 172 180
pull()は、tibbleやdata.frameから「特定の1列だけをベクトルとして取り出す」関数です。列が一つと決まっているので、出力は決まってアトミックベクトルとなります。
# peopleからweight属性を取り出す。(people$weightと同じ)
pull(people, weight) # 出力はアトミックベクトル
## [1] 55 65 80
# 列番号で指定(2列目 = height)
pull(people, 2)
## [1] 165 172 180
# 複数の列番号を指定するとエラーとなる
pull(people,3:4)
## Error in `pull()`:
## ! `!!enquo(var)` must select exactly one column.
他方で、
select(df,n)は、データフレームの特定の列を参照しますが、複数の列も参照することができます。重要な点として、列の数が一つでも複数でも、出力形式はtibbleとなります。
# height列とweight列を抽出
select(people, height, weight)
## # A tibble: 3 × 2 ## height weight ## <dbl> <dbl> ## 1 165 55 ## 2 172 65 ## 3 180 80
以下は、意味としては
people$heightと同じですが、 出力がtibble形式となることに注意してください。これは、のちの
select(people,height)
## # A tibble: 3 × 1 ## height ## <dbl> ## 1 165 ## 2 172 ## 3 180
slice(df, n)はデータフレームからn行目のみを切り出します。出力は、再びデータフレームとなります。スライスは横方向に切り取る感じですね。
# 2行目だけを抽出
slice(people, 2)
## # A tibble: 1 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 B 172 65 M
# 2〜3行目を抽出
slice(people,2:3)
## # A tibble: 2 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 B 172 65 M ## 2 C 180 80 M
relocate関数は、列の順番を入れ替えることができます。`
# height列を先頭に移動
print(people); relocate(people, height)
## # A tibble: 3 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 A 165 55 F ## 2 B 172 65 M ## 3 C 180 80 M
## # A tibble: 3 × 4 ## height name weight gender ## <dbl> <chr> <dbl> <chr> ## 1 165 A 55 F ## 2 172 B 65 M ## 3 180 C 80 M
# name列をgender列の前に移動
relocate(people,name,.before = gender )
## # A tibble: 3 × 4 ## height weight name gender ## <dbl> <dbl> <chr> <chr> ## 1 165 55 A F ## 2 172 65 B M ## 3 180 80 C M
# name列をgender列の後に移動
relocate(people,name,.after = gender )
## # A tibble: 3 × 4 ## height weight gender name ## <dbl> <dbl> <chr> <chr> ## 1 165 55 F A ## 2 172 65 M B ## 3 180 80 M C
filter():行を絞る(条件で抽出)select():列を選ぶ(必要な列だけ残す)mutate():列を作る・書き換える(新しい情報を加える)summarise():要約する(平均や合計などを1行にまとめる)arrange():並べ替える(昇順・降順)|>
を使うと、処理の流れを上から下へ読めるようになります。library(dplyr)
people = tibble(
name = c("A", "B", "C", "D", "E"),
height = c(165, 172, 180, 175, 160),
weight = c(55, 65, 80, 70, 50),
gender = c("F","M","M","F","F")
)
people
## # A tibble: 5 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 A 165 55 F ## 2 B 172 65 M ## 3 C 180 80 M ## 4 D 175 70 F ## 5 E 160 50 F
filter():行を絞る(条件で抽出)
filter(df,条件)は、dfを第2引数の条件に従って、特定の行だけをsliceする関数です。
# 以下は同じ結果となります。
filter(people, row_number() == 2); slice(people,2)
## # A tibble: 1 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 B 172 65 M
## # A tibble: 1 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 B 172 65 M
# 身長が170cm以上の人だけ抽出
filter(people, height >= 170)
## # A tibble: 3 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 B 172 65 M ## 2 C 180 80 M ## 3 D 175 70 F
# 条件を複数指定することも可能(AND条件)
filter(people, height >= 170, gender == "M")
## # A tibble: 2 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 B 172 65 M ## 2 C 180 80 M
# OR条件の場合は | を使う
filter(people, height >= 180 | weight >= 70)
## # A tibble: 2 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 C 180 80 M ## 2 D 175 70 F
select():列を選ぶ(必要な列だけ)既に説明していますが復習も兼ねて。
ここでも重要なのは、仮に出力の列数が一つでも、
常にtibble形式で扱われる点にあります。
# 特定の列を残す
select(people, name, height)
## # A tibble: 5 × 2 ## name height ## <chr> <dbl> ## 1 A 165 ## 2 B 172 ## 3 C 180 ## 4 D 175 ## 5 E 160
# 列を除外する場合はマイナス指定
select(people, -gender)
## # A tibble: 5 × 3 ## name height weight ## <chr> <dbl> <dbl> ## 1 A 165 55 ## 2 B 172 65 ## 3 C 180 80 ## 4 D 175 70 ## 5 E 160 50
# ヘルパー関数も使える
select(people, starts_with("h")) # "height"列を抽出
## # A tibble: 5 × 1 ## height ## <dbl> ## 1 165 ## 2 172 ## 3 180 ## 4 175 ## 5 160
mutate():列を新しく作る・書き換える
mutate()は、既存のデータに新しい列を追加したり、既存の列を計算で書き換えたりする関数です。 Excelの新しい列に「計算式を入力して値を作る」ようなイメージです。
# BMI列を新しく作成
people2 = mutate(people,
BMI = round(weight / (height/100)^2, 1)
)
people2
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 A 165 55 F 20.2 ## 2 B 172 65 M 22 ## 3 C 180 80 M 24.7 ## 4 D 175 70 F 22.9 ## 5 E 160 50 F 19.5
# 既存列の変換も可能(heightをm単位に)
mutate(people2, height = height / 100)
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 A 1.65 55 F 20.2 ## 2 B 1.72 65 M 22 ## 3 C 1.8 80 M 24.7 ## 4 D 1.75 70 F 22.9 ## 5 E 1.6 50 F 19.5
summarise():要約(グループごとに集計)
summarise()は、データ全体やグループごとに、平均・合計・最大値などの要約統計量を計算する関数です。
mean(), sum(), max(),
min(), sd() などの関数と組み合わせて使うgroup_by() と組み合わせて
グループごとに1行ずつ要約することもできるgroup_by()
と組み合わせることで、カテゴリごとの平均・件数・最大値などの集計が可能になる
summarise()は「データを要約する」関数、
group_by()は「グループ分けする」関数です。
この2つを組み合わせることで、「性別ごとの平均」や「条件ごとの件数」などを簡単に計算でき、
グループが多いほど出力行も増えるという仕組みになっています。
# 全体の統計量をまとめる
summarise(people2,
mean_height = mean(height), # 平均
mean_weight = mean(weight),
max_height = max(height), # 最大値
sd_height = sd(height), # 標準偏差
total_weight = sum(weight), # 合計
n = n() # 件数
)
## # A tibble: 1 × 6 ## mean_height mean_weight max_height sd_height total_weight n ## <dbl> <dbl> <dbl> <dbl> <dbl> <int> ## 1 170. 64 180 7.96 320 5
# group_by() で性別ごとにグループ化してから要約
people_grouped = group_by(people2, gender)
people_grouped #内部的にグループ化されていますが(2行目)、見た目はほぼ変わらない。
## # A tibble: 5 × 5 ## # Groups: gender [2] ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 A 165 55 F 20.2 ## 2 B 172 65 M 22 ## 3 C 180 80 M 24.7 ## 4 D 175 70 F 22.9 ## 5 E 160 50 F 19.5
#男女別に各統計量を出力(2行となる!)
summarise(people_grouped,
mean_height = mean(height),
max_weight = max(weight),
mean_BMI = mean(BMI),
sd_BMI = sd(BMI),
n = n() # 各グループの件数
)
## # A tibble: 2 × 6 ## gender mean_height max_weight mean_BMI sd_BMI n ## <chr> <dbl> <dbl> <dbl> <dbl> <int> ## 1 F 167. 70 20.9 1.80 3 ## 2 M 176 80 23.4 1.91 2
arrange():並べ替え(行の順序を変える)
arrange()は、指定した列の値をもとに行の並び順を変える関数です。
Excelで「並べ替え」ボタンを押すのと同じイメージで、
昇順(小さい順)・降順(大きい順)・複数条件でのソートが可能です。
desc() を使う# 身長の昇順(デフォルト)
arrange(people2, height)
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 E 160 50 F 19.5 ## 2 A 165 55 F 20.2 ## 3 B 172 65 M 22 ## 4 D 175 70 F 22.9 ## 5 C 180 80 M 24.7
# BMIの降順(大きい順)
arrange(people2, desc(BMI))
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 C 180 80 M 24.7 ## 2 D 175 70 F 22.9 ## 3 B 172 65 M 22 ## 4 A 165 55 F 20.2 ## 5 E 160 50 F 19.5
# 複数の条件で並べ替え(性別ごとに、BMIの降順)
arrange(people2, gender, desc(BMI))
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 D 175 70 F 22.9 ## 2 A 165 55 F 20.2 ## 3 E 160 50 F 19.5 ## 4 C 180 80 M 24.7 ## 5 B 172 65 M 22
# 名前順(アルファベット順)に並べ替え
arrange(people2, name)
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 A 165 55 F 20.2 ## 2 B 172 65 M 22 ## 3 C 180 80 M 24.7 ## 4 D 175 70 F 22.9 ## 5 E 160 50 F 19.5
# 並べ替え結果を保存したい場合
people_sorted = arrange(people2, desc(height))
people_sorted
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 C 180 80 M 24.7 ## 2 D 175 70 F 22.9 ## 3 B 172 65 M 22 ## 4 A 165 55 F 20.2 ## 5 E 160 50 F 19.5
arrange()は、データを「並べ替えて見やすくする」関数です。filter()やmutate()と組み合わせて、条件抽出 → 計算 → 並べ替え のように使うことで、整った順序の結果を得ることができます。
%>%)を使う%>% は「そして次に」を意味します。x %>% f()
は「xをf()に渡す」という構文です。library(dplyr)
people = tibble(
name = c("A", "B", "C", "D", "E"),
height = c(165, 172, 180, 175, 160),
weight = c(55, 65, 80, 70, 50),
gender = c("F","M","M","F","F")
)
people
## # A tibble: 5 × 4 ## name height weight gender ## <chr> <dbl> <dbl> <chr> ## 1 A 165 55 F ## 2 B 172 65 M ## 3 C 180 80 M ## 4 D 175 70 F ## 5 E 160 50 F
people2 = mutate(people,
BMI = round(weight / (height/100)^2, 1)
)
people3 = filter(people2, BMI >= 22)
people4 = arrange(people3, desc(BMI))
people5 = select(people4, name, gender, BMI)
people5
## # A tibble: 3 × 3 ## name gender BMI ## <chr> <chr> <dbl> ## 1 C M 24.7 ## 2 D F 22.9 ## 3 B M 22
手順は正しいけれど、途中でデータ名が増えてしまい読みにくい…。
ちなみに、これを一つの式で書くとさらに大変なことになります。
select(arrange(filter(mutate(people,
BMI = round(weight / (height/100)^2, 1)),
BMI >= 22),
desc(BMI)),
name, gender, BMI)
people %>%
mutate(BMI = round(weight / (height/100)^2, 1)) %>%
filter(BMI >= 22) %>%
arrange(desc(BMI)) %>%
select(name, gender, BMI)
## # A tibble: 3 × 3 ## name gender BMI ## <chr> <chr> <dbl> ## 1 C M 24.7 ## 2 D F 22.9 ## 3 B M 22
データの流れが「上から下へ」読めるようになり、 一連の処理が自然に理解できます。
💡 RStudio のショートカット
| OS | 操作キー | 出力 |
|---|---|---|
| macOS | ⌘ + Shift + M | %>% |
| Windows / Linux | Ctrl + Shift + M | %>% |
このショートカットは、
magrittrやdplyrで使われる
tidyverse パイプ演算子%>%を自動で挿入します。
people %>%
mutate(BMI = round(weight / (height/100)^2, 1)) %>%
filter(BMI >= 2) %>%
head() # 途中で確認
## # A tibble: 5 × 5 ## name height weight gender BMI ## <chr> <dbl> <dbl> <chr> <dbl> ## 1 A 165 55 F 20.2 ## 2 B 172 65 M 22 ## 3 C 180 80 M 24.7 ## 4 D 175 70 F 22.9 ## 5 E 160 50 F 19.5
group_by() + summarise()
もスッキリ書ける# パイプを使わないとネスト(入れ子)が深くなる
people %>%
mutate(BMI = round(weight / (height/100)^2, 1)) %>%
group_by(gender) %>%
summarise(
mean_height = mean(height),
mean_BMI = mean(BMI),
n = n()
)
## # A tibble: 2 × 4 ## gender mean_height mean_BMI n ## <chr> <dbl> <dbl> <int> ## 1 F 167. 20.9 3 ## 2 M 176 23.4 2
以下は
group_by()とmutate()を組み合わせた例です(グループ毎の平均値と最大スコア)。
新たな変数を追加するときにも、グループ毎の集計結果を返すことは可能です。
summarize()と異なり、グループ毎に、統計値が重複することに注意してください。
data <- tibble(
group = c("A", "A", "A", "B", "B", "B"),
score = c(80, 90, 85, 70, 75, 65)
)
data %>%
group_by(group) %>%
mutate(mean_score = mean(score), max_score = max(score))
## # A tibble: 6 × 4 ## # Groups: group [2] ## group score mean_score max_score ## <chr> <dbl> <dbl> <dbl> ## 1 A 80 85 90 ## 2 A 90 85 90 ## 3 A 85 85 90 ## 4 B 70 70 75 ## 5 B 75 70 75 ## 6 B 65 70 75
| 構文 | 意味 | 読み方 |
|---|---|---|
x %>% f() |
f(x) |
「xをfに渡す」 |
x %>% f(y) |
f(x, y) |
「xをfに渡してyを使う」 |
x %>% f() %>% g() |
g(f(x)) |
「xをfに通してgに渡す」 |
x %>% f() %>% g() %>% h() |
h(g(f(x))) |
省略 |
パイプは“関数をつなぐ線路”。
これまで学んだ関数を「流れ」として表現できるようになります。
ここまでで、
filter()・select()・mutate()・summarise()・arrange()と
パイプ%>%の使い方を学びました。
ここでは、実務や研究でよく使う追加関数をまとめて紹介します。
複数のデータフレームを共通の列(キー)で結合します。
すべての関数で基本構文は同じで、*_join(x, y, by = "共通列名")の形で使います。
| 関数名 | 内容 |
|---|---|
left_join() |
左側の行をすべて保持(対応しない右側はNA) |
inner_join() |
両方に共通する行のみ残す |
full_join() |
すべての行を結合(存在しない要素はNA補完) |
semi_join() |
左側に「対応のある行」だけ残す(右側列は持たない) |
anti_join() |
左側に「対応のない行」だけ残す |
# 顧客データと注文データを作成
customers = tibble(
id = 1:3,
name = c("A", "B", "C")
)
orders = tibble(
id = c(1, 1, 3, 4),
item = c("Book", "Pen", "Bag", "Lamp")
)
customers
## # A tibble: 3 × 2 ## id name ## <int> <chr> ## 1 1 A ## 2 2 B ## 3 3 C
orders
## # A tibble: 4 × 2 ## id item ## <dbl> <chr> ## 1 1 Book ## 2 1 Pen ## 3 3 Bag ## 4 4 Lamp
# left_join:左側(customers)の行をすべて保持
left_join(customers, orders, by = "id")
## # A tibble: 4 × 3 ## id name item ## <dbl> <chr> <chr> ## 1 1 A Book ## 2 1 A Pen ## 3 2 B <NA> ## 4 3 C Bag
# inner_join:両方に共通するidのみ残す
inner_join(customers, orders, by = "id")
## # A tibble: 3 × 3 ## id name item ## <dbl> <chr> <chr> ## 1 1 A Book ## 2 1 A Pen ## 3 3 C Bag
💬 補足
-left_join()は最もよく使われる結合。欠損があっても左側の情報を保持できる。
-inner_join()は両方に存在するデータのみ抽出。
- いずれも出力は tibble形式。
-semi_join()/anti_join()は「対応の有無でフィルタしたいとき」に使う。
- 結合前にdistinct()でキー重複を確認しておくと安全。
mutate()と組み合わせて、値に応じてカテゴリを付けることができます。
case_when()は複数条件に対応し、if_else()はシンプルな二分岐に向いています。
case_when():複数条件に基づいてカテゴリを作成# テスト得点データ
scores = tibble(
name = c("A", "B", "C", "D", "E"),
score = c(92, 75, 63, 88, 55)
)
scores
## # A tibble: 5 × 2 ## name score ## <chr> <dbl> ## 1 A 92 ## 2 B 75 ## 3 C 63 ## 4 D 88 ## 5 E 55
# 成績を条件で分類
mutate(scores,
grade = case_when(
score >= 80 ~ "A",
score >= 65 ~ "B",
TRUE ~ "C"
)
)
## # A tibble: 5 × 3 ## name score grade ## <chr> <dbl> <chr> ## 1 A 92 A ## 2 B 75 B ## 3 C 63 C ## 4 D 88 A ## 5 E 55 C
💬 解説
-case_when()は「if / else if / else」を一括で書ける構文。
- 条件は上から順に評価され、最初にTRUEになった式が採用されます。
-TRUE ~ "C"は「どれにも当てはまらない場合」のデフォルト処理です。
if_else():単純な二分岐(TRUE/FALSEで分ける)mutate(scores,
pass = if_else(score >= 70, "合格", "不合格")
)
## # A tibble: 5 × 3 ## name score pass ## <chr> <dbl> <chr> ## 1 A 92 合格 ## 2 B 75 合格 ## 3 C 63 不合格 ## 4 D 88 合格 ## 5 E 55 不合格
💬 解説
-if_else(条件, TRUEの値, FALSEの値)の形で使います。
- ベクトル全体に適用され、結果はtibbleの新しい列として追加されます。
-if_else()はifelse()よりも型が厳密で、安全に使える点が特徴です。
mutate(scores,
grade = case_when(
score >= 90 ~ "S",
score >= 80 ~ "A",
score >= 65 ~ "B",
TRUE ~ "C"
),
result = if_else(score >= 70, "Pass", "Fail")
)
## # A tibble: 5 × 4 ## name score grade result ## <chr> <dbl> <chr> <chr> ## 1 A 92 S Pass ## 2 B 75 B Pass ## 3 C 63 C Fail ## 4 D 88 A Pass ## 5 E 55 C Fail
💬 まとめ
- 単純な条件 →if_else()
- 複数条件 →case_when()
- いずれもmutate()内で使うと列を自動的に追加できる。
- 条件は論理値(TRUE/FALSE)で評価され、結果はベクトルとして返る。
across()複数の列に同じ処理を一括で適用できる関数です。
mutate() や summarise() の中で使われ、
「同じ演算を何列にも繰り返したい」場合に便利です。
# サンプルデータ
data = tibble(
name = c("A", "B", "C"),
math = c(80, 90, 70),
english = c(85, 88, 78),
science = c(82, 95, 75)
)
data
## # A tibble: 3 × 4 ## name math english science ## <chr> <dbl> <dbl> <dbl> ## 1 A 80 85 82 ## 2 B 90 88 95 ## 3 C 70 78 75
# 数値列だけを抽出して平均を計算
summarise(data,
across(where(is.numeric), mean)
)
## # A tibble: 1 × 3 ## math english science ## <dbl> <dbl> <dbl> ## 1 80 83.7 84
💬
where(is.numeric)は「数値列をすべて選ぶ」という条件指定。
文字列列(name)は自動的に除外されます。
# すべての数値列を100で割る
mutate(data,
across(where(is.numeric), ~ .x / 100)
)
## # A tibble: 3 × 4 ## name math english science ## <chr> <dbl> <dbl> <dbl> ## 1 A 0.8 0.85 0.82 ## 2 B 0.9 0.88 0.95 ## 3 C 0.7 0.78 0.75
💬
~ .x / 100は「各列の値(.x)を100で割る」という意味。
across()は「繰り返し書かずにすむ」ための仕組みです。
# "m"で始まる列だけ2倍に
mutate(data,
across(starts_with("m"), ~ .x * 2)
)
## # A tibble: 3 × 4 ## name math english science ## <chr> <dbl> <dbl> <dbl> ## 1 A 160 85 82 ## 2 B 180 88 95 ## 3 C 140 78 75
💬
starts_with("m")のほかに、ends_with()やcontains()なども使えます。
列名パターンに基づく一括処理が可能です。
mutate() → 値を変換・作成summarise() → 要約統計where(is.numeric)、starts_with()、contains().bygroup_by() を使わず、簡潔にグループ集計できます(dplyr
1.1以降)。今のところ、本授業ではgroup_by()の使用していくつもりです。
summarise(df, mean_height = mean(height), .by = gender)
mutate(df, z = scale(weight), .by = gender)
| 関数 | 内容 | 使用例 |
|---|---|---|
slice_min() |
指定列の最小値行を取得 | slice_min(df, order_by = BMI, n = 3) |
slice_max() |
指定列の最大値行を取得 | slice_max(df, order_by = BMI, n = 3) |
slice_sample() |
ランダムに行を抽出 | slice_sample(df, n = 5) |
| 機能 | 関数 | 使用例 |
|---|---|---|
| 列名を一括変更 | rename_with() |
rename_with(df, toupper, starts_with("col")) |
| グループ内の件数やユニーク数 | n() / n_distinct() |
summarise(df, n = n(), uniq = n_distinct(name), .by = gender) |
| 条件付きフィルタ | if_any() / if_all() |
filter(df, if_any(ends_with("_flag"), ~ .x == TRUE)) |
| 欠損値補完 | coalesce() |
mutate(df, x = coalesce(x, 0)) |
ungroup()anti_join() でキーの不一致を確認distinct(df, id, .keep_all = TRUE)people_grouped %>% ungroup() %>% summarise(mean_BMI = mean(BMI))
以下から、奇数偶数の好み実験結果の架空(N=2865)のデータをインポートしてください。
url = "https://lab.kenrikodaka.com/_download/csv/oddeven_2865.csv"
data.df = read.csv(url)
head(data.df) #最初の6行をちょっと出し(NAは未定)
## month day preference gender age domhand ## 1 10 26 ODD MALE 19 RIGHT ## 2 4 6 ODD MALE NA <NA> ## 3 9 14 EVEN FEMALE 20 RIGHT ## 4 1 21 ODD FEMALE 17 RIGHT ## 5 4 7 EVEN FEMALE 20 RIGHT ## 6 7 27 EVEN FEMALE 18 RIGHT
library(tidyverse) # csvをtibble形式で読み込めるようになります。
data.tb = read_csv(url) #読み込み関数が微妙に違うので注意
head(data.tb)
## # A tibble: 6 × 6 ## month day preference gender age domhand ## <dbl> <dbl> <chr> <chr> <dbl> <chr> ## 1 10 26 ODD MALE 19 RIGHT ## 2 4 6 ODD MALE NA <NA> ## 3 9 14 EVEN FEMALE 20 RIGHT ## 4 1 21 ODD FEMALE 17 RIGHT ## 5 4 7 EVEN FEMALE 20 RIGHT ## 6 7 27 EVEN FEMALE 18 RIGHT
# 以下では、単にdataとします。
data = data.tb
head(data, 10)
## # A tibble: 10 × 6 ## month day preference gender age domhand ## <dbl> <dbl> <chr> <chr> <dbl> <chr> ## 1 10 26 ODD MALE 19 RIGHT ## 2 4 6 ODD MALE NA <NA> ## 3 9 14 EVEN FEMALE 20 RIGHT ## 4 1 21 ODD FEMALE 17 RIGHT ## 5 4 7 EVEN FEMALE 20 RIGHT ## 6 7 27 EVEN FEMALE 18 RIGHT ## 7 6 15 ODD MALE 19 RIGHT ## 8 5 26 EVEN FEMALE 19 RIGHT ## 9 2 5 EVEN MALE 18 RIGHT ## 10 7 23 EVEN MALE 18 RIGHT
翻訳すると以下の様になります。
誕生日と奇数偶数の好みに関するアンケートの架空のデータ(2865人分)です。 month(誕生月)・day(誕生日)・preference(奇数が好き:ODD, 偶数が好き:EVEN) gender(男性:MALE, 女性:FEMALE)・$domhand(利き手が左:LEFT, 利き手が右:RIGHT) age(年齢)
data2 = data %>%
group_by(gender) %>%
summarise(
n_even = sum(preference == "EVEN"),
n_odd = sum(preference == "ODD"),
prop_even = n_even / (n_even + n_odd)
)
print(data2)
## # A tibble: 2 × 4 ## gender n_even n_odd prop_even ## <chr> <int> <int> <dbl> ## 1 FEMALE 1044 559 0.651 ## 2 MALE 650 612 0.515
data3 = data %>%
filter(gender == "FEMALE") %>%
group_by(month) %>%
summarise(
n_even = sum(preference == "EVEN"),
n_odd = sum(preference == "ODD"),
prop_even = n_even / (n_even + n_odd)
) %>%
arrange(desc(prop_even))
print(data3)
## # A tibble: 12 × 4 ## month n_even n_odd prop_even ## <dbl> <int> <int> <dbl> ## 1 4 84 29 0.743 ## 2 12 92 32 0.742 ## 3 2 74 29 0.718 ## 4 6 110 45 0.710 ## 5 8 109 49 0.690 ## 6 11 84 48 0.636 ## 7 1 93 57 0.62 ## 8 9 83 52 0.615 ## 9 10 78 49 0.614 ## 10 3 87 56 0.608 ## 11 7 84 59 0.587 ## 12 5 66 54 0.55
data4 = data %>%
mutate(month2 = if_else(month%%2==0, "EVEN", "ODD")) %>%
group_by(month2, gender) %>%
summarise(
n_even = sum(preference == "EVEN"),
n_odd = sum(preference == "ODD"),
prop_even = n_even / (n_even + n_odd)
) %>%
relocate(gender) %>%
arrange(gender)
print(data4)
## # A tibble: 4 × 5 ## # Groups: month2 [2] ## gender month2 n_even n_odd prop_even ## <chr> <chr> <int> <int> <dbl> ## 1 FEMALE EVEN 547 233 0.701 ## 2 FEMALE ODD 497 326 0.604 ## 3 MALE EVEN 334 273 0.550 ## 4 MALE ODD 316 339 0.482