Rの%>%を理解したい
Rを楽しむための道のりの一つには
「中置関数と仲良くする」というステップがあると思います。
多くの方が恩恵を受けているであろうtidyverse
の中にある、
中置関数の一つパイプ(%>%
)に関し、
以前こんな記事
を書いてみたのですが、
その頃よりちょっぴり書きたいネタが増えてしまいました。
そこで今回は%>%
を実際に作る過程を通じて
中置関数を楽しんでもらいたいなと思います。
実際のコード
最も単純にパイプを表現すると以下の式になると思います。
普通に読むと'%>%'
は引数にa
とf
をとって、
f(a)
を返す関数だよ、と言っています。
'%>%' <- function (a,f) f(a)
ここでのミソは2つあります。
1つは左辺、LHS(上の'%>%'
側)の制約で、
記号を%
で挟むのが作法であるようです。
そしてそれをクウォート(''
)してあげます。
もう1つは項のとり方で、
適用する際はfunction
関数の第一引数を左にとり、
第二引数を右に取ります。
何を言っているんだ、という場合は次の例でスッキリするかもしれません。
iris %>% head
## 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
上を見ると、確かに
先ほど定義した中置関数(%>%
)の左側にiris
データを置いて
右側にhead
関数を置くと、
head(iris)
の意味になることになります。
pipeの何が嬉しいのか
R界隈で今更(というと使っていない方に失礼ですが)pipeの
ありがたさを伝える意味はなさそうです。
が、一応説明すると、以上の%>%
を使うと
関数の組み合わせの見通しが良くなります。
まずデータa
に対して関数f
と関数g
を
適用するためにはg(f(a))
とせねばなりません。
しかし a %>% f %>% g
とかくと
「あぁa
をf
に入れてg
に入れたのか」と分かります。
その他の中置関数の使い方
その便利さは語っても語りきれませんが、
列にアクセスするdf$col
も中置換数であることを
思い出すと極めて稀に美味しいことがおきます。
例えば$
も中置関数なので、
以下のように通常の呼び出し方ができます。
"$"(iris,Species)
これと先ほどの話を組み合わせてみます。
先ほど作ったのは項を一つしかとらない関数に限定
されているので、もっと柔軟な関数として
magrittr
パッケージの%>%
を借ります。
library(magrittr)
# さっき作ったのは上書きする
"%>%" <- magrittr::"%>%"
iris %>% "$"(Species)
するとiris
のSpecies
列へアクセスできます。
これが一体なんの役に立つかというと、
パイプを切らせたくない時、です。
データをガチャガチャしたあとで選択、
とかだと、わけても可読性が上がるわけでもないのに加えて
一時変数が増えるデメリットがあります。
iris %>% 長い操作 %>% "$"(Species)
あるいは apply系なんかにも中置関数使えますね!
mapply("*",c(1,2,3),c(1,2,3))
# 当然、以下だとエラーになる。
# mapply(*,c(1,2,3),c(1,2,3))
# エラー: 予想外の '*' です in "mapply(*"