Menu

R のパイプ演算子: %>% とネイティブの |>

%>% の意味、base R のネイティブパイプ |> の仕組み、それぞれの規則とプレースホルダ、そして新しいコードではどちらを使うべきかを解説します。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

パイプが解決する問題

パイプは手前の値を受け取り、後ろの関数呼び出しに渡します — x |> f()f(x) を意味します。3 段や 4 段つなぐまでは些細な書き換えに聞こえるでしょう。パイプがないと、多段階の変換は入れ子になり、入れ子の呼び出しは逆順に読むことになります。最初に 起こることが 最も内側 にあるのです。

round(sqrt(x), 1) を読むには、真ん中(x)から始めて外側へ(sqrt、次に round)進み、末尾の , 1) がどの呼び出しのものかを追い続けなければなりません。3 段でも煩わしく、データフレーム用の動詞とそれぞれの複数引数を伴う 5 段になると、本当に追いにくくなります。人がよく取る代替策 — 中間段階をすべて tmp1, tmp2, tmp3 に保存する — は、誰も必要としない名前でワークスペースを散らかします。

パイプは、その連鎖を実際に起こる順序で書き直します。x を取り、次に 平方根を取り、次に 丸める。

ネイティブパイプ |>

R 4.1 以降、パイプは言語そのものに組み込まれています — パッケージは不要です。|> は直前の値を次の呼び出しの 第 1 引数 として挿入します。

c(1, 4, 9, 16) |> sqrt() |> round(1) はちょうど round(sqrt(c(1, 4, 9, 16)), 1) です — R は構文解析時に文字どおり一方をもう一方へ書き換えるので、実行時のオーバーヘッドはゼロです。しかしコードはレシピのように上から下へ読めるようになります。まずデータ、次に各変換を順番に。これはデータ用のツールに限らず、あらゆる 関数 で機能します — mtcars |> head(3) は最初から最後まで素の base R です。

パイプが「第 1 引数がデータ」である関数といかに相性が良いかに注目してください。headsortuniquesummary、そしてすべての dplyr の動詞はそのように設計されています。だからこそ R ではパイプラインがこれほど自然に感じられるのです。

|> の規則

ネイティブパイプは意図的に厳格です。3 つの規則でほぼすべてを網羅できます。

1. 次の段は括弧付きの呼び出しでなければならない。 x |> sqrt は構文エラーです。x |> sqrt() と書かなければなりません。

c(1, 4, 9) |> sqrt     # Error: The pipe operator requires a function call as RHS
c(1, 4, 9) |> sqrt()   # correct

2. 値は第 1 引数の位置に入る。 自分で書いた追加の引数はその後ろにそのまま残ります — x |> round(1)round(x, 1) です。

3. それ以外の位置に渡すには、名前付き引数とともに _ プレースホルダを使う(R 4.2 以降)。典型例は lm です。第 1 引数が式、第 2 引数がデータなので、データフレームを流し込むには data = _ が必要になります。

_ は 1 回だけ、しかも名前付き引数としてのみ使えます。それでは制約が強すぎる場合は、無名関数へパイプしましょう。無名関数なら値を好きな場所に置けます。

ラムダは括弧で包んでから () で呼び出します — これで規則 1 が満たされます。1 つのパイプラインの中でこれを何度もやっているなら、その段はおそらく名前付きの関数にすべきです。

magrittr のパイプ %>%

言語にパイプが入る前は、magrittr パッケージ がそれを提供しており、%>% は tidyverse コードの象徴になりました — dplyr を読み込めば自動的に使えます。この 10 年に書かれたほぼすべての dplyr のチュートリアルやスクリプトで目にするはずです。

library(dplyr)

mtcars %>%
  filter(mpg > 30) %>%
  select(mpg, wt)

%>% はパッケージ由来なので、これらの例は素の R セッションでは実行できません。library(dplyr)(または library(magrittr))を忘れると、まさに Error: could not find function "%>%" が出ます。

よくあるケースでの挙動は |> と同一です。直前の値を次の呼び出しの第 1 引数に渡します。ただし magrittr の方が寛容です。

c(1, 4, 9) %>% sqrt                 # bare function name - no parentheses needed

mtcars %>% lm(mpg ~ wt, data = .)   # . placeholder, usable anywhere

c(-2, 3) %>% { max(abs(.)) }        # . can even appear several times, in nested calls

|> と %>%: 重要な違い

第 1 引数へのパイプライン — 実コードの圧倒的大部分がこれです — においては、両者は交換可能です。違いは周縁部にあります。

  • 利用可能性: |> は base R 4.1 以降。%>% は magrittr(通常は dplyr 経由)が必要です。
  • 括弧: |>sqrt() を要求します。%>% は裸の sqrt を受け入れます。
  • プレースホルダ: |>_ を 1 回、名前付き引数としてのみ使います(4.2 以降)。%>%. をどこにでも、何回でも、入れ子の呼び出しの中でも使えます。
  • 速度: |> は構文解析時に入れ子の呼び出しへ書き換えられます — コストはゼロです。%>% は通常の関数呼び出しで、わずかな(実際上は無視できる)オーバーヘッドがあります。

ここに %>% を誤りとするものは何もありません — 実戦で鍛えられており、わずかに柔軟です。しかし |> を超えてできることはすべてラムダで実現でき、base のパイプは依存関係を必要としません。

どちらを使うべきか

新しいコードでは |> を使いましょう。言語の一部であり、R 4.1 以降が動くところならどこでも機能し、パッケージ不要で、その厳格さは機能として読めます — パイプラインは単純なまま保たれるか、名前付き関数へリファクタリングされます。

とはいえ、%>% を淀みなく読める 必要があります。tidyverse のコードベース、Stack Overflow の回答、2014 年以降に書かれた大半の R 本はそれで満ちているからです。既存の dplyr スタイルを持つチームは一貫性のために %>% を使い続けることが多く、それは妥当な判断です — 最悪の選択は 1 つのファイルで両方の演算子を混在させることです。どちらを書くにせよ、共通する慣習が 1 つあります。長いパイプラインでは各段を 1 行ずつに置き、パイプを行末に付けましょう。そうすればレシピが手順のリストとして読めます。

apply ファミリー と同じ感覚がここでも当てはまります。パイプは直線的で段階を追う変換のためのものです。計算が分岐したり、中間結果が 2 回必要になったりする場合は、すべてを 1 本の連鎖に押し込まず、適切な名前の変数に代入しましょう。

この記事のまとめ

  • パイプは直前の値を次の呼び出しに渡します。x |> f() |> g()g(f(x)) を、起こる順序で書いたものです。
  • |> は base R(4.1 以降)です。括弧が必要で、第 1 引数を狙い、_ プレースホルダは名前付き引数とともに使います(4.2 以降)。
  • %>% は magrittr / tidyverse です。裸の名前が許され、. プレースホルダはどこにでも置けます — ただしパッケージが必要です。
  • 新しいコードでは |> を優先し、それ以外の場所では %>% をまばたきせずに読めるようにしましょう。
  • パイプは直線的なレシピに向きます。分岐するロジックには名前付き変数がふさわしいのです。

次は パッケージ — %>% や dplyr、そして R の他の 2 万を超える拡張が実際にどこから来るのかを見ていきます。

よくある質問

R の %>% はどういう意味ですか?

%>% は magrittr のパイプです。手前の値を受け取り、直後の呼び出しの第 1 引数として渡します。つまり x %>% f() %>% g()g(f(x)) を意味します。magrittr パッケージ由来で、dplyr や tidyverse を読み込むと自動的に使えるようになります — base R の一部ではありません。

R で |> を使うのにパッケージは必要ですか?

いいえ。|> はネイティブパイプで、バージョン 4.1 以降の base R に組み込まれています — 何もインストールしていない素の R セッションで動きます。パッケージが必要なのは %>% の方です(magrittr、あるいは dplyr のようにそれを再エクスポートするもの)。

R の |> と %>% の違いは何ですか?

どちらも直前の値を次の呼び出しに渡します。|> は base R で、明示的な括弧が必要(x |> sqrt())で、_ プレースホルダは名前付き引数でのみ使えます。%>% は magrittr が必要で、関数名を裸で書け(x %>% sqrt)、. プレースホルダはどこにでも、何回でも置けます。よくある第 1 引数のケースでは挙動は同一です。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める