今回は、R言語のコードそのものを見やすくするという話です。
Rでのコードの書き方
R言語では、型を指定しないオブジェクトにデータやその下処理・解析結果を一時的に保持するのが典型的です。例えば以下のコードは、入力データ、下処理後データ、解析結果がそれぞれオブジェクトに保存されています。入力データは、下処理にかけられ、その結果が別のオブジェクトとして保存されます。その結果が、解析にとっての入力になり、さらに結果のオブジェクトが保存されるという流れです。
#入力データ input <- data.frame(x = rnorm(100), y = rnorm(100)) #下処理 subdata <- subset(input,x > 0) #解析 result <- lm(y ~ x, data = subdata) #結果の表示 summary(result)
上記のコードは、一時的な結果を保持するオブジェクトが利用されています。メモリを節約するために、なるべく一時的な保持のオブジェクトを作らないように書くと、次のようになります。
summary(lm(y ~ x, data = subset(data.frame(x = rnorm(100),y = rnorm(100)),x>0)))
確かにメモリは節約できているかもしれませんが、この書き方は関数が複雑な入れ子になっていて、コードが読みにくいものになっています。このように標準的なコードでは、メモリの管理もしくは読みにくさがトレードオフの関係になってしまいがちです。
パイプ処理による解決
上記の問題の解決手段の一つがパイプ処理です。今回は、magrittrというパッケージを利用して、より読みやすいコードの書き方をまとめます*1。なお、magrittrなどのパイプ処理を実現するパッケージの解説記事は、以下がおすすめです。
%>%
%>%というパイプ処理では、パイプの左側の結果を、パイプ右側に配置した関数の最初の引数に割り当てます。または、明示的に.で割り当て位置を決定することもできます。試みに上記のコードをパイプ処理を利用して書いてみましょう。
library(magrittr) input <- data.frame(x = rnorm(100),y = rnorm(100)) %>% subset(x >0) %>% lm(y ~ x, data = .) %>% summary
このように書くとinputとして作成したデータがsubset関数、lm関数、summary関数と順に処理されていく様子を容易に読み取れます。とても便利なのですが、1点注意するとしたら、これがbaseパッケージではできないことです。そのためmagrittrパッケージの導入に同意した人にしかコードをシェアできないということを忘れないようにしましょう。
*1:pipeRというパッケージもあるようです。