[R] このコードなんで動くの?
このコードなんで動くの?
iris |> dplyr::select(Sepal.Length) |> sum() #876.5
irisというデータセットについて、がく辺の長さの合計を求めているというのは分かる。
ただ、最近Rを触っていない自分はこう思ってしまう。
-
iris
Sepal.Length
なんて変数を定義した覚えがない -
sum()
って0
だよな
再現性を担保するために書いておくと rocker/verse:4.1.2
って docker イメージで動作確認している。
まず iris
なんだけれど、これは datasets という package の一部らしい。
だから datasets::iris
という使い方もできる。
ここまではよいのだが、じゃあなぜ iris
のみで使えるのか?
どうも最初から datasets package がロードされてしまっているようだ。
print(.packages())
# [1] "stats" "graphics" "grDevices" "utils" "datasets" "methods" "base"
ということはもちろん明示的にアンロードすることもできる。
detach("package:datasets", unload=TRUE)
iris # Error: object 'iris' not found
次に sum()
なんだけれど、少し簡略化して以下のコードについて考えてみる。
1:5 |> sum()
|>
はパイプ演算子で、左項の値を右項の関数呼び出しの引数として扱うもの。
それは分かるんだけれど sum()
って評価されると 0
だよな。
sum() # 0
じゃあこう書いてもいいということか(違う)。
1:5 |> 0 # Error: The pipe operator requires a function call as RHS
要するに評価のタイミングがピンと来ていないんだよな。
Stack Overflow で quote()
してみなって助言があったから従ってみる。
quote(1:5 |> sum()) # sum(1:5)
これが何を意味しているかっていうと、値が評価されるよりも前に sum(1:5)
に変換されているということ。
残る疑問点は dplyr::select(Sepal.Length)
だけ。
もちろん Sepal.Length
なんていう変数は定義されていない。
Sepal.Length
# Error: object 'Sepal.Length' not found
おそらくさっきの |>
と sum()
の件と同じく、評価のタイミングが問題なのだろうという気はする。
深入りしない程度に dplyr::select
のコードを見てくると、渡された Sepal.Length
などはすぐに評価されないよう expr()
で包んで後続の処理に渡されている。
今回の調べものはこれくらいにしておくけれど、Rって奥が深いのね。