医療職からデータサイエンティストへ

統計学、機械学習に関する記事をまとめています。

これは便利! R パイプ %>% の使い方

データフレームを扱う時にとても便利なのがパイプ!
ggplotでしか使ったことがなかったけれど、調べてみるととても便利そうなので使い方をまとめます!   medi-data.hatenablog.com

パイプとは?

パイプとは、途中経過を変数に代入せずそのまま次の処理へ渡せるとても便利な機能です。 文字では伝わりにくいので、具体的にみてみましょう!
前回は{dplyr}を使いましたが、どうやら{magrittr}の方が使いやすいそうです!

> library(magrittr)
>library(dplyr)#データフレーム処理には読み込んでおくと便利
> cars$wether <- sample(c("sunny" , "rainy"),nrow(cars) , replace = TRUE)
> head(cars)
  speed dist wether
1     4    2  rainy
2     4   10  rainy
3     7    4  rainy
4     7   22  sunny
5     8   16  rainy
6     9   10  rainy

お馴染み車の走る速さと停車距離のデータセットのcarsを使います。 仮想的にお天気の変数を加えてみました。 ここで晴れの場合のみの平均スピードを計算したいとします。すると

> speeds <- cars$speed[cars$wether == "sunny"]
> mean(speeds)
[1] 16.24

となりますね。mean関数の中に入れてもいいですが、読みにくくなります。

しかしパイプを使うと...

> cars$speed[cars$wether == "sunny"] %>% mean()
[1] 16.24

こんな感じになり、どんな処理をしたのかがわかりやすくなりました!

パイプの基本使用法

このようにパイプ%>%の左側で処理をした値を右側の関数にそのまま入れてくれるので、一気に処理をすることができます。
基本的には関数の第一に引数に代入されるようですが、(.)を使うと明示的に代入位置を指定できます。

>#適当な関数を作成
> f <- function(x = "第一引数だよ" , y = "第二引数だよ" ){
+   print(x)
+   print(y)
+ }
> f()
[1] "第一引数だよ"
[1] "第二引数だよ"
>#何も指定がなければ第一引数に値が渡される。
> "パイプだよ" %>% f()
[1] "パイプだよ"
[1] "第二引数だよ"
># . を使うと明示的に値を渡す引数を指定できる。
> "パイプだよ" %>% f(,.)
[1] "第一引数だよ"
[1] "パイプだよ"

さらに便利に使いたい

単純な処理ではあまり恩恵が分かりませんが、パイプにはさらなる力があります!

途中でグラフも書きたい "%T>%"

例えば先ほどの例で、グラフも一緒に書きたい時、Tをつけた%T>%を使うとグラフも一気に書くことができます。

> #これだと上手くいかない
> cars$speed[cars$wether == "sunny"] %>%
+   plot(xlab = "", ylab ="")  %>% 
+   mean()
[1] NA
 警告メッセージ: 
 mean.default(.):  argument is not numeric or logical: returning NA

>#%T>%を使うと上手くいく
> cars$speed[cars$wether == "sunny"] %T>%
+   plot(xlab = "", ylab ="")  %>% 
+   mean()
[1] 16.24

f:id:h-wadsworth02:20181222084316p:plain:w400

データフレームの変数をそのまま使いたい "%$%"

データフレームの変数をそのまま使える%$%というのもあります。 filter関数も使って

> cars %>% filter(wether == "sunny") %$% mean(speed)
[1] 16.24
>#cars[cars$wether == "sunny" , ]と同じ

さらに同時に複数の関数に値を渡すこともできて

> cars %>% filter(wether == "sunny") %$% {
+   print(mean(speed))
+   print(mean(dist))
+   ggplot(data = (.) , aes(x = speed , y = dist))+
+     geom_point()
+   
+ }
[1] 16.24
[1] 42.24

f:id:h-wadsworth02:20181222084405p:plain
ここでは、speedとdistの平均をprintして、ggplotで可視化しています。data = (.)は、filter(wether == "sunny")を受け取っています。

途中経過を変数に代入したい

最後に途中の値を変数に代入したい時は、永続代入演算子もしくは通常の代入演算子が使えます。

>#{}で括って、二つ以上の処理を行う時は永続代入にする。
> cars %>% filter(wether == "sunny") %$% {
+   mean(speed) ->> meansp
+   mean(dist) ->> meandist
+ }
>#一つで良ければ、通常の代入演算子でOK
> cars %>% filter(wether == "sunny") %$% 
+   mean(speed) -> meansp2
> 

まとめ

処理を一気通貫して行えるパイプは、読みやすさ、記載のシンプルさから知っておいて損はない機能です。私もこれからどんどん使っていきます!

最後までお読み頂き、ありがとうございました!

参考にさせて頂いたサイト

【R】絶対に身につけて欲しいR術 - 歩いたら休め

pipe中毒になったら、更にわがままな人間になった - Qiita