web-dev-qa-db-ja.com

なぜ `[`は `サブセットよりも優れているのですか?

Data.frameをフィルタリングする、つまり特定の条件を満たす行を抽出する必要がある場合は、subset関数を使用します。

subset(airquality, Month == 8 & Temp > 90)

[関数ではなく:

airquality[airquality$Month == 8 & airquality$Temp > 90, ]

私の好みには2つの主な理由があります。

  1. 私は、コードが左から右に読みやすくなっていることに気付きました。 Rについて何も知らない人でも、上記のsubsetステートメントが何をしているのかわかります。

  2. 列はselect式では変数として参照できるため、キーストロークをいくつか省くことができます。上記の例では、airqualityと1回、[と3回入力するだけでした。

だから私はsubsetを短くして読みやすく、私の仲間のRコーダーにその美しさを主張しているので、どこでもsubsetを使って幸せに暮らしていました。しかし昨日、私の世界はバラバラになりました。 subsetのドキュメントを読みながら、私はこのセクションに気付きました:

警告

これは対話的に使うことを意図した便利な機能です。プログラミングのためには、[のような標準的なサブセット化関数を使用するのがより良いです、そして特に、引数サブセットの非標準的な評価は予期しない結果をもたらすことがありえます。

誰かが作者の意味を明確にするのを手伝ってくれる?

まず、 "インタラクティブに使用するため"とはどういう意味ですか?スクリプトをバッチモードで実行するのとは対照的に、対話型セッションが何であるかはわかっていますが、違いが生じるはずがありません。

それでは、「引数サブセットの非標準的な評価」を説明してください。それがなぜ危険なのか、例を挙げてください。

383
flodel

この質問は@Jamesのコメントでよく回答されており、Hadley Wickhamによるsubset(およびそのような機能)の危険性についての優れた説明が示されています [here] 。それを読みに行って!

これはやや長めの読みなので、ここでHadleyが使用した例で「何が問題になる可能性があるのか​​」という問題に最も直接的に対処する例を記録すると便利です。

Hadleyは次の例を提案しています。次の関数を使ってデータフレームをサブセット化してから並べ替えるとします。

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
  scramble(subset(x, condition))
}

subscramble(mtcars, cyl == 4)

これはエラーを返します。

Eval(expr、envir、enclos)のエラー:オブジェクト 'cyl'が見つかりません

なぜなら、Rはもはや 'cyl'と呼ばれるオブジェクトを見つける場所を「知らない」からです。彼はまた、偶然にも地球環境に「cyl」と呼ばれる物がある場合に起こり得る、本当に奇妙なことを指摘しています。

cyl <- 4
subscramble(mtcars, cyl == 4)

cyl <- sample(10, 100, rep = T)
subscramble(mtcars, cyl == 4)

(それらを実行して自分の目で確かめてください、それはかなりクレイジーです。)

229
joran

[も速いです:

require(microbenchmark)        
microbenchmark(subset(airquality, Month == 8 & Temp > 90),airquality[airquality$Month == 8 & airquality$Temp > 90,])
    Unit: microseconds
                                                           expr     min       lq   median       uq     max neval
                     subset(airquality, Month == 8 & Temp > 90) 301.994 312.1565 317.3600 349.4170 500.903   100
     airquality[airquality$Month == 8 & airquality$Temp > 90, ] 234.807 239.3125 244.2715 271.7885 340.058   100
26
bartektartanus