何気ない関数・演算子の導入がプロジェクトを傷つけた
ちょっと前の話。私が手を加えたコードが動かないという相談を受けた。早速手元で試してみたが自分の環境では再現できている。確認のために再実行してもらうと確かに結果が違うようだ。なぜだろう。結論を書いてしまうと、問題は %<>%
演算子にあった。
%<>%
演算子、この演算子について知っている人はどのくらいいるだろうか。この演算子は、見た目も %>%
と類似している。そう、 magrittr パッケージが提供するパイプ演算子の一種である。その働きは %>%
演算子と同様、パイプの左辺に与えられたオブジェクトに対し右辺で指定した関数に渡すものである。そして、その結果を左辺のオブジェクトに代入する。
library(magrittr) x <- letters[1:3] x %<>% toupper() x ## [1] "A" "B" "C"
この演算子の何が良いのかというと、%>%
を使った場合には次のように書く必要のあるコードを簡略化できることである。
x <- x %>% toupper()
パイプ処理の結果を元のオブジェクトに保存するのであれば、x <- x
は冗長に思える。そこで %<>%
を使う。一方で、それだけ、という話でもある。
%>%
はtidyverseの処理の中で利用しているので知っている。しかし %<>%
についてはその機能を知らない。知らない人からすると%<>%
をtypoだと思って%>%
に直してしまうかもしれない。そうすると私の意図した結果が得られないのもの納得できる。
何気ないパイプ %>% が非パイプユーザーの心をきずつけた
— h(o x o_)m< わかりみ。 (@hoxo_m) February 7, 2018
私にとって当然であることがメンバーの常識であるとは限らない。dplyr や tidyr パッケージの個々の関数について、その機能を把握するのにもある程度の時間がかかる。まずは個々の関数がどのパッケージから読み込まれているのかを理解させないといけない気もする。その場合には名前空間を指定してdplyr::mutate()
のような書き方をしているが、package::function()
が何を意味しているのか、名前空間とは何かがわかっていないと意味がない。これは自分も理解するのに時間が必要だった記憶がある。少なくとも本を読んだり誰かから説明を受けない限りは理解できなかっただろう。
tidyverseに含まれるパッケージやパイプ処理は大変便利であるが、それは初心者向きではない。
tidyverse is premature for you guys
(書いてない)
tidyverseの真価を知るには、Rで標準利用できる関数で手間のかかる処理をパイプ演算子と組み合わせて利用することで効果的になることを理解してもらうのが必要だ。
You can not use #tidyverse without base R. It's not a dichotomy. Pick the tools that make you most effective.
— Hadley Wickham (@hadleywickham) August 31, 2017
これは自分が感じていることであり、Hadley自身もそのようなことを言っていたのでちょっと安心した。
... チームで分析プロジェクトを進行していく際は、メンバー間で技術や知見の足並みを揃えることは大事だと考えているが、それは高い水準にするのでなく、今の状態で 共通認識として参加するメンバーが理解している範囲の水準にする方が良い気がしてきた。
パイプに加えて、先端的なパッケージや開発が盛んなパッケージの導入は便利だ。しかしそれは破滅の始まりになる危険性をはらんでいる。
ということを上の記事を読んで思った。ついつい忘れがちになってしまうが一度考える時間を設けたい。