参考にした本
今年の夏ごろに買いました。
パイプ演算子(%>%)を見るに「ひょっとして面倒なループなのではないか」という印象を抱いてしまい、意味もなく敬遠していました。が、いざ使ってみるととても直観的で操作しやすいです。Excelでいうピボットテーブルのような機能です。
必要な準備
インストール
> install.packages("dplyr") > library(dplyr)
データセットを読み込む
Rの内蔵データセットのアイリスを使用。含まれる変数は、
Sepal.Length:がく辺の長さ
Sepal.Width:がく辺の幅
Petal.Length:花びらの長さ
Petal.Width:花びらの幅
Species:品種("setosa","versicolor","virginica"の3種類)
> head(iris) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa
フィルターをかける
一つの条件
アイリスのデータから
- Sepal.Lengthが5以上
を満たす行のみを抽出。変数の分布をみて外れ値を除外するときなどに便利。
加工前データ(iris)と加工後データ(iris.2)を分ける。
> iris.2 <- iris %>% + filter(Sepal.Length >= 5) > head(iris.2) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 5.0 3.6 1.4 0.2 setosa 3 5.4 3.9 1.7 0.4 setosa 4 5.0 3.4 1.5 0.2 setosa 5 5.4 3.7 1.5 0.2 setosa 6 5.8 4.0 1.2 0.2 setosa
複数条件の場合
- Sepal.Lengthが5以上
- Speciesがvirginica
の条件をどちらも満たす行を取り出す場合は、&(AND)を使って
> iris.2 <- iris %>% + filter(iris$Sepal.Length >= 5 & Species == "virginica")
どちらか一方を満たす行を抽出する場合は、|(OR)を使って
> iris.2 <- iris %>% + filter(iris$Sepal.Length >= 5 | Species == "virginica")
条件の否定
- Sepal.Lengthが5以上ではない
- Speciesがvirginicadではない
個体を選びたい場合、!を使う。今回のように種類が少なければ否定を使わなくても書けますが、カテゴリー数の多いデータを扱う際に便利。
> iris.2 <- iris %>% + filter(!(iris$Sepal.Length >= 5 | Species == "virginica"))
グループごとに集計する
カウントする
- Speciesごとの数を集計する
group_by()で集計単位を指定し、mutate()で新しくnという名前の列を作る
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(n=n())
group_by()はあくまで集計の単位なので、データセットの構造自体を変える訳ではありません。Speacisごとの数だけ確認したいときは、distinct()で「重複するSpeaciesを削除=ユニークなSpeaciesだけ残す」操作を行う。すると、Speaciesの数=3行だけ残る。keep.allは集計対象以外の列も残す、というオプション。
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(n =n()) %>% + distinct(Species,.keep_all = TRUE) > head(iris.2) # A tibble: 3 x 6 # Groups: Species [3] Sepal.Length Sepal.Width Petal.Length Petal.Width Species n <dbl> <dbl> <dbl> <dbl> <fct> <int> 1 5.1 3.5 1.4 0.2 setosa 50 2 7 3.2 4.7 1.4 versicolor 50 3 6.3 3.3 6 2.5 virginica 50
平均や分散を出す
- SpeciesごとにSepal.Length(がく片の長さ)の平均と標準偏差を算出する
mutate()でmeanとsdという名前の新しい列を作る。記述統計量を算出するsummerize()というコマンドもある。
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(mean = mean(Sepal.Length), + sd = sd(Sepal.Length)) %>% + distinct(Species,.keep_all = TRUE) > iris.2 # A tibble: 3 x 7 # Groups: Species [3] Sepal.Length Sepal.Width Petal.Length Petal.Width Species mean sd <dbl> <dbl> <dbl> <dbl> <fct> <dbl> <dbl> 1 5.1 3.5 1.4 0.2 setosa 5.01 0.352 2 7 3.2 4.7 1.4 versicolor 5.94 0.516 3 6.3 3.3 6 2.5 virginica 6.59 0.636
複数の単位で集計
データセットの中には、大カテゴリー、中カテゴリー、・・という風に集計単位が複数になる場合もある。その場合はgroup_by(A,B,・・・)のように、2つ以上の変数を入れる
一回集計したあとに再度集計
データセットによっては同じidのデータが複数行に渡って含まれる場合もある。一度id別に平均等を算出し、更にidのカテゴリーごとに集計する場合、group_by(id), mutate(new=mean(A)),group_by(category)という風に、group_byを2回に分けて使うこともできる。
条件下で新たな変数を作る
- Spetal.Length(がく片の長さ)が5以下だと1をとるフラグを作成する
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(flg = ifelse(Sepal.Length <= 5,1,0)) > head(iris.2) # A tibble: 6 x 6 # Groups: Species [1] Sepal.Length Sepal.Width Petal.Length Petal.Width Species flg <dbl> <dbl> <dbl> <dbl> <fct> <dbl> 1 5.1 3.5 1.4 0.2 setosa 0 2 4.9 3 1.4 0.2 setosa 1 3 4.7 3.2 1.3 0.2 setosa 1 4 4.6 3.1 1.5 0.2 setosa 1 5 5 3.6 1.4 0.2 setosa 1 6 5.4 3.9 1.7 0.4 setosa 0
列名の変更と並び変え
- Speciesごとの平均と標準偏差のみ出力する
前処理の終盤で行う操作。必要な列だけをselect()で選ぶ。並び替えも同時にできる。
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(mean = mean(Sepal.Length), + sd = sd(Sepal.Length)) %>% + distinct(Species,.keep_all = TRUE) %>% + select(Species,mean,sd) > iris.2 # A tibble: 3 x 3 # Groups: Species [3] Species mean sd <fct> <dbl> <dbl> 1 setosa 5.01 0.352 2 versicolor 5.94 0.516 3 virginica 6.59 0.636
列名を変える
- 列名を日本語に変える
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(mean = mean(Sepal.Length), + sd = sd(Sepal.Length)) %>% + distinct(Species,.keep_all = TRUE) %>% + select(Species,mean,sd) %>% + rename(品種 = Species, + 平均 = mean, + 標準偏差 = sd) > iris.2 # A tibble: 3 x 3 # Groups: 品種 [3] 品種 平均 標準偏差 <fct> <dbl> <dbl> 1 setosa 5.01 0.352 2 versicolor 5.94 0.516 3 virginica 6.59 0.636
並び順を変える(ソートする)
- 平均が大きい順に並び替える
arrange()で並び替え。デフォルトは降順なので、"-"(マイナス)またはdesc()で逆にする。
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(mean = mean(Sepal.Length), + sd = sd(Sepal.Length)) %>% + distinct(Species,.keep_all = TRUE) %>% + select(Species,mean,sd) %>% + rename(品種 = Species, + 平均 = mean, + 標準偏差 = sd) %>% + arrange(desc(平均)) > iris.2 # A tibble: 3 x 3 # Groups: 品種 [3] 品種 平均 標準偏差 <fct> <dbl> <dbl> 1 virginica 6.59 0.636 2 versicolor 5.94 0.516 3 setosa 5.01 0.352
エクセルに出力する
そのまま出力
> write.xlsx(iris.2,"iris2.xlsx")
集計単位ごとにシートを分ける
split()をかましてからエクセルに出力する。1品種1シートごとに結果が出力される。
> iris.2 <- iris %>% + group_by(Species) %>% + mutate(mean = mean(Sepal.Length), + sd = sd(Sepal.Length)) %>% + distinct(Species,.keep_all = TRUE) %>% + select(Species,mean,sd) %>% + rename(品種 = Species, + 平均 = mean, + 標準偏差 = sd) %>% + arrange(desc(平均)) %>% + split(.,.$品種) > write.xlsx(iris.2,"iris2.xlsx")