第24章 パイプ演算子%>%
について
こいつはtidyverse
内のmagrittr
というパッケージの機能で、パイプ演算子あるいは単にパイプと呼ばれたりします。
以下のサイトが参考になりました。
- R for Data ScienceのPipes
- magrittrのvignetteの訳
##
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
##
## set_names
## The following object is masked from 'package:tidyr':
##
## extract
24.1 基本的な使い方
基本的に%>%
は左辺の出力を右辺の関数の第1引数にします。
つまり、f %>% g
はg(f)
と同値です。
ちなみに、RStudioではShift + Ctrl + M
で入力します。
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species
## setosa :50
## versicolor:50
## virginica :50
##
##
##
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species
## setosa :50
## versicolor:50
## virginica :50
##
##
##
これだけだとパイプ演算子のご利益は分かりにくいですが、コードが長くなるにつれてその力を発揮します。
例えば、iris
の各品種について各変数の平均と中央値を求めてみます。
パイプ演算子を使うと次のように一行のコードで書くことができます。
iris %>%
pivot_longer(-Species, names_to = "var", values_to = "val") %>%
group_by(var, Species) %>%
summarise(mean = mean(val),
median = median(val))
iris %>%
pivot_longer(-Species, names_to = "var", values_to = "val") %>%
group_by(var, Species) %>%
summarise(mean = mean(val),
median = median(val)) %>%
knitr::kable()
## `summarise()` regrouping output by 'var' (override with `.groups` argument)
var | Species | mean | median |
---|---|---|---|
Petal.Length | setosa | 1.462 | 1.50 |
Petal.Length | versicolor | 4.260 | 4.35 |
Petal.Length | virginica | 5.552 | 5.55 |
Petal.Width | setosa | 0.246 | 0.20 |
Petal.Width | versicolor | 1.326 | 1.30 |
Petal.Width | virginica | 2.026 | 2.00 |
Sepal.Length | setosa | 5.006 | 5.00 |
Sepal.Length | versicolor | 5.936 | 5.90 |
Sepal.Length | virginica | 6.588 | 6.50 |
Sepal.Width | setosa | 3.428 | 3.40 |
Sepal.Width | versicolor | 2.770 | 2.80 |
Sepal.Width | virginica | 2.974 | 3.00 |
これをパイプ演算子を使わないと、次のようになります。
summarise(group_by(pivot_longer(iris, -Species, names_to = "var", values_to = "val"), var, Species), mean = mean(val), median = median(val))
summarise(group_by(pivot_longer(iris, -Species, names_to = "var", values_to = "val"), var, Species), mean = mean(val), median = median(val)) %>%
knitr::kable()
## `summarise()` regrouping output by 'var' (override with `.groups` argument)
var | Species | mean | median |
---|---|---|---|
Petal.Length | setosa | 1.462 | 1.50 |
Petal.Length | versicolor | 4.260 | 4.35 |
Petal.Length | virginica | 5.552 | 5.55 |
Petal.Width | setosa | 0.246 | 0.20 |
Petal.Width | versicolor | 1.326 | 1.30 |
Petal.Width | virginica | 2.026 | 2.00 |
Sepal.Length | setosa | 5.006 | 5.00 |
Sepal.Length | versicolor | 5.936 | 5.90 |
Sepal.Length | virginica | 6.588 | 6.50 |
Sepal.Width | setosa | 3.428 | 3.40 |
Sepal.Width | versicolor | 2.770 | 2.80 |
Sepal.Width | virginica | 2.974 | 3.00 |
あるいは適当なオブジェクトを作成して次のようにします。
temp <- pivot_longer(iris, -Species, names_to = "var", values_to = "val")
temp <- group_by(temp, var, Species)
temp <- summarise(temp, mean = mean(val), median = median(val))
temp
temp <- pivot_longer(iris, -Species, names_to = "var", values_to = "val")
temp <- group_by(temp, var, Species)
temp <- summarise(temp, mean = mean(val), median = median(val))
## `summarise()` regrouping output by 'var' (override with `.groups` argument)
var | Species | mean | median |
---|---|---|---|
Petal.Length | setosa | 1.462 | 1.50 |
Petal.Length | versicolor | 4.260 | 4.35 |
Petal.Length | virginica | 5.552 | 5.55 |
Petal.Width | setosa | 0.246 | 0.20 |
Petal.Width | versicolor | 1.326 | 1.30 |
Petal.Width | virginica | 2.026 | 2.00 |
Sepal.Length | setosa | 5.006 | 5.00 |
Sepal.Length | versicolor | 5.936 | 5.90 |
Sepal.Length | virginica | 6.588 | 6.50 |
Sepal.Width | setosa | 3.428 | 3.40 |
Sepal.Width | versicolor | 2.770 | 2.80 |
Sepal.Width | virginica | 2.974 | 3.00 |
このように考えるとパイプ演算子のご利益は次のようにまとめられます。
- 処理をする順番に関数が登場するので可読性を高めることができる。
- 一行でコードを書くことができるので無駄なオブジェクトを作らなくてよい。
24.2 データの代入
データを加工する際、パイプを使うと基本的にはこのようになります。
iris <- iris %>%
mutate(species = case_when(Species == "setosa" ~ 0,
Species == "versicolor" ~ 1,
Species == "virginica" ~ 2))
summary(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species species
## setosa :50 Min. :0
## versicolor:50 1st Qu.:0
## virginica :50 Median :1
## Mean :1
## 3rd Qu.:2
## Max. :2
しかし、左から右に流れるべきと思う場合は次のように書くこともできます。
iris %>%
mutate(species = case_when(Species == "setosa" ~ 0,
Species == "versicolor" ~ 1,
Species == "virginica" ~ 2)) -> iris
summary(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species species
## setosa :50 Min. :0
## versicolor:50 1st Qu.:0
## virginica :50 Median :1
## Mean :1
## 3rd Qu.:2
## Max. :2
あるいは%<>%
という演算子を使うこともできます。
iris %<>%
mutate(species = case_when(Species == "setosa" ~ 0,
Species == "versicolor" ~ 1,
Species == "virginica" ~ 2))
summary(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species species
## setosa :50 Min. :0
## versicolor:50 1st Qu.:0
## virginica :50 Median :1
## Mean :1
## 3rd Qu.:2
## Max. :2
24.3 左辺の参照
基本的にはパイプ演算子の左辺を右辺の第1引数にしますが、.
を使うことで任意の引数にすることができます。
例えば、iris
でsetosa
を除外して回帰分析をしたい場合、第1引数はformula
なので普通はパイプで繋げることはできないが、以下のように書くことができます。
##
## Call:
## lm(formula = Sepal.Length ~ Sepal.Width, data = .)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.0032 -0.3877 -0.0774 0.3200 1.7381
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.0934 0.4844 6.387 5.70e-09 ***
## Sepal.Width 1.1033 0.1675 6.585 2.27e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.5547 on 98 degrees of freedom
## Multiple R-squared: 0.3068, Adjusted R-squared: 0.2997
## F-statistic: 43.36 on 1 and 98 DF, p-value: 2.27e-09
また、%$%
という演算子は右辺において左辺のデータを参照せずに変数名を指定することができます。
したがって、次のように書くこともできます。
##
## Call:
## lm(formula = Sepal.Length ~ Sepal.Width)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.0032 -0.3877 -0.0774 0.3200 1.7381
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.0934 0.4844 6.387 5.70e-09 ***
## Sepal.Width 1.1033 0.1675 6.585 2.27e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.5547 on 98 degrees of freedom
## Multiple R-squared: 0.3068, Adjusted R-squared: 0.2997
## F-statistic: 43.36 on 1 and 98 DF, p-value: 2.27e-09
これは、次のコードと同値です。
##
## Call:
## lm(formula = .$Sepal.Length ~ .$Sepal.Width)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.0032 -0.3877 -0.0774 0.3200 1.7381
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.0934 0.4844 6.387 5.70e-09 ***
## .$Sepal.Width 1.1033 0.1675 6.585 2.27e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.5547 on 98 degrees of freedom
## Multiple R-squared: 0.3068, Adjusted R-squared: 0.2997
## F-statistic: 43.36 on 1 and 98 DF, p-value: 2.27e-09
24.4 複数の出力
.
を使うことで複数の出力を行うことも可能です。
## [1] 5.843333
## [1] 5.8
## [1] 0.6856935
$T>$
という演算子を使うと右辺は評価されるが、返り値は左辺のままになります。
例えば、plot()
に流すことで図を出力しつつ、iris
をsummary()
にも流すことができます。
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species species
## setosa :50 Min. :0
## versicolor:50 1st Qu.:0
## virginica :50 Median :1
## Mean :1
## 3rd Qu.:2
## Max. :2
これは、以下のコードと同値です。
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species species
## setosa :50 Min. :0
## versicolor:50 1st Qu.:0
## virginica :50 Median :1
## Mean :1
## 3rd Qu.:2
## Max. :2