magrittrのvignetteの訳

以下の文章は[magrittr - Ceci n'est pas un pipe](https://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html)を訳したものです( ﾟДﾟ)y─┛~~

Abstract
--------

*magrittr*(洗練されたフランス語のアクセントで発音する)パッケージは、2つの目的をもつ。1つは開発時間を短縮すること、もう1つはコードの可読性と保守性を向上させることだ。要はコードがイケてる感じになるのだ( ﾟДﾟ)y─┛~~

この謙虚な目的を達成するために、*magrittr*(アクセントを忘れないでもらいたい)は新しく**パイプ**風演算子である`%>%`を導入する。この演算子を使うことで、値を演算子の先の式や関数呼び出しに渡すことができるようになる。例えば`f(x)`は`x %>% f`と書ける。これは他の言語を考えてみると、決して新しい概念というわけでもない。F\#で広く使われている`|>`演算子や、(言うまでもないことだが)Unixのパイプはmagrittrパッケージを開発する動機となっている。

このvignetteではmagrittrの主な機能を解説するとともに、初期のリリースに追加したいくつかの機能も紹介する。

入門と基本
----------

はじめのうちは`%>%`が本当に役に立つのかどうか疑問に思うかもしれない。しかし、この文法の変更がコードの読み書きをより直感的にするということをきっと気付いてもらえることと思う。

例を考えてみよう。以下ではRに付属している`mtcars`データセットを軽く集計・変更している。

``` r
library(magrittr)

car_data <- 
  mtcars %>%
  subset(hp > 100) %>%
  aggregate(. ~ cyl, data = ., FUN = . %>% mean %>% round(2)) %>%
  transform(kpl = mpg %>% multiply_by(0.4251)) %>%
  print
```

|  cyl|    mpg|    disp|      hp|  drat|    wt|   qsec|    vs|    am|  gear|  carb|        kpl|
|----:|------:|-------:|-------:|-----:|-----:|------:|-----:|-----:|-----:|-----:|----------:|
|    4|  25.90|  108.05|  111.00|  3.94|  2.15|  17.75|  1.00|  1.00|  4.50|  2.00|  11.010090|
|    6|  19.74|  183.31|  122.29|  3.59|  3.12|  17.98|  0.57|  0.43|  3.86|  3.43|   8.391474|
|    8|  15.10|  353.10|  209.21|  3.23|  4.00|  16.77|  0.00|  0.14|  3.29|  3.50|   6.419010|

データである`mtcars`(これはデータフレームだ)から初め、サブセットを抽出し、シリンダー数毎に情報を集約し、mile/gallonを補う情報としてkm/Lの列を追加した。最後に結果を代入する前にprintした。手順が**問題を考える際の論理的な順序**になっているという点に注目して欲しい。つまり、「データ -&gt; 変換 -&gt; 集約」の順だ。そしてコードはこの順序で実行される。これはレシピのように読みやすく、簡単に追うことができる。

上記コードに対する恐ろしい代案はこうだ。

``` r
car_data <- 
  transform(aggregate(. ~ cyl,
                      data = subset(mtcars, hp > 100),
                      FUN = function(x) round(mean(x, 2))),
            kpl = mpg * 0.4251)
```

多数の括弧が混乱をもたらしているこのコードの解読は難しい問題となるだろう。これを書いたのが自分ではない場合は尚更だ。

magrittrを使えば、`aggregate`で使用する集約用の関数を組み立てるのも簡単になるという点にも注目して欲しい。パイプラインを`.`から始めるだけで関数定義になるのだ。これは`*aaply`族の関数を利用する際にも便利だ。

2番目の例は、一時変数を使うことによって(magrittrを使えば一時変数作成も回避できるのだが)、もう少し良くできるかもしれない。しかし、例として提示したような煩雑なコードはしばしば見かけるものだ。

他にも利点はある。何か別の手順を途中に追加したくなったとしよう。パイプラインを使っていれば、これは非常に簡単にできる。しかし、標準的なRのコードで同じことをするのは少し大変だろう。

先程の例が示すmagrittrの特徴はまとめるとこうだ。

1.  標準では、パイプ演算子の左側の結果(LHS: left-hand side)は、右側(RHS: right-hand side)の第一引数として使われる。例中では、`subset`と`transform`で使用されている。
2.  `%>%`は関数の内部で入れ子にして使うこともできる。例えば引数の指定部分などだ。例では`mpg`から`kpl`を計算する部分で使用している。
3.  LHSが第一引数以外の部分で必要な場合は、ドット`.`をプレースホルダとして使用できる。例では`aggregate`の中で使用した。
4.  formula中のドットとプレースホルダとしてのドットが混同されることはない。`aggregate`の中では2つの使用法が併存している。
5.  必要な引数がLHSただ一つである場合には、空の括弧を省略することができる。これは`print`の部分で使用している。`print`は`LHS %>% print()`とも書けるし、もちろん`LHS %>% print(.)`とも書ける。
6.  `.`から始めるパイプラインは無名関数を作成する。これは`aggregate`内で集約関数を定義する部分で使用した。

例に含まれていない機能として、無名関数(あるいはlambda)へのパイプがある。標準の関数定義機能を用いて、以下のように実行できる。

``` r
car_data %>%
  (function(x){
    if(nrow(x) > 2)
      rbind(head(x, 1), tail(x, 1))
    else x
  })
```

しかし、magrittrでは短縮形として以下の書き方もできるようにしている。

``` r
car_data %>%
{
  if(nrow(.) > 2)
    rbind(head(., 1), tail(., 1))
  else .
}
```

    ##   cyl mpg disp  hp drat wt qsec vs am gear carb     kpl
    ## 1   4  26  108 111    4  2   18  1  1    4    2 11.0526
    ## 3   8  15  350 192    3  4   17  0  0    3    4  6.3765

右辺は無名関数の本体だけになり、右辺の自然な拡張になっていることが分かるだろう。もちろん、もっと長い、複雑な関数を使うことだってできる。

最初の例では無名関数を括弧で括っていた。パイプを行う前に右辺を評価したい場合には、このように括弧を使用する。

あまり役に立たないだろうが、例を示しておこう。

``` r
1:10 %>% (substitute(f(), list(f = sum)))
```

    ## [1] 55

その他のパイプ演算子
--------------------

magrittrは他に3つのパイプ演算子を提供している。これらは`%>%`ほど汎用性は無いが、特定の状況では役に立つこともあるだろう。

まずは"tee"演算子こと`%T>%`だ。これは`%>%`のように機能するが、右辺の結果を返す代わりに左辺の結果をそのまま返すという特徴がある。これは、パイプライン中で副作用のみを利用したい場合(printやplot、loggingなど)に便利だ。以下に例を示そう(plot結果は省略した)。

``` r
rnorm(200) %>%
  matrix(ncol = 2) %T>%
  plot %>% # plotは通常返り値が無い
  colSums
```

``` r
set.seed(1)
rnorm(200) %>%
  matrix(ncol = 2) %>%
  colSums
```

    ## [1] 10.888737 -3.780808

plotは通常返り値が無いので、パイプラインの途中に挟むとそこで処理が止まってしまう。しかし、`%T>%`を使うことで`colSums`には`plot`の結果ではなく`matrix(ncol = 2)`の結果が受け渡されるので、処理を継続できるのだ。

2つめの演算子は"exposition"演算子こと`%$%`だ。この演算子を使うと、左辺のオブジェクトに含まれる名前を右辺で参照できるようになる。実質的には、これは`with`関数の短縮形のようなものだ。これは、`lm`や`aggregate`が持っているようなdata引数を持たない関数を使う場合に便利だ。例を示そう。

``` r
iris %>%
  subset(Sepal.Length > mean(Sepal.Length)) %$%
  cor(Sepal.Length, Sepal.Width)
```

    ## [1] 0.3361992

``` r
data.frame(z = rnorm(100)) %$%
  ts.plot(z)
```

最後に複合代入演算子`%<>%`の説明をしよう。これはパイプラインの最初で使用することができる。この演算子を使うと、パイプラインの結果は左辺のオブジェクトに代入される。つまり、`foo <- foo %>% bar %>% baz`を`foo %<>% bar %>% baz`のように書けるということだ。もう一つ例を示しておこう。

``` r
iris$Sepal.Length %<>% sqrt
```

`%<>%`は、代入演算子`<-`を使う場面ならどこでも使える。

-   `x %<>% foo %>% bar`
-   `x[1:10] %<>% foo %>% bar`
-   `x$baz %<>% foo %>% bar`

Aliases
-------

magrittrは`%>%`演算子だけでなく、加算や乗算などの操作をmagrittrの構文に馴染ませるためのエイリアスをいくつか提供している。

``` r
rnorm(1000) %>%
  multiply_by(5) %>%
  add(5) %>%
  {
    cat("平均: ", mean(.),
        "分散: ", var(.), "\n")
    head(.)
  }
```

    ## 平均:  4.825097 分散:  27.5386

    ## [1]  7.047009 13.444366 12.932942  3.345461 -6.426178 17.488308

上記の例は以下の書き方と同じ意味になる。

``` r
rnorm(1000) %>% `*`(5) %>% `+`(5) %>%
{
  cat("平均: ", mean(.), "分散: ", var(.), "\n")
  head(.)
}
```

詳しい説明は`?multiply_by`を確認してほしい。

Development
-----------

-   [tidyverse/magrittr: Improve the readability of R code with the pipe](https://github.com/tidyverse/magrittr)