[解決済み] なぜ `vapply` は `sapply` よりも安全なのですか?
質問
ドキュメントによると
vapply
はsapply
と似ていますが、戻り値の型があらかじめ指定されているので、より安全に[...]使用することができます。
なぜそれが一般的により安全なのか、例を挙げて詳しく説明していただけませんか?
追伸:答えはわかっていますし、私はすでに
sapply
. ただ、このSOに素敵な答えがあれば、同僚にそれを示すことができるのに、と思っています。どうか、「マニュアルを読め」的な回答は無しでお願いします。
どのように解決するのですか?
すでに指摘されているように
vapply
は2つのことをします。
- わずかな速度改善
- 限定的な戻り値の型チェックを提供することにより、一貫性を向上させました。
2点目は、エラーを事前にキャッチしやすくなり、より堅牢なコードにつながるという大きなメリットです。 この戻り値のチェックは、別途
sapply
の後に
stopifnot
を使用して、戻り値が期待したものと一致することを確認しますが
vapply
の方が少し簡単です(カスタムのエラーチェックのコードで境界内の値をチェックできるなど、より限定的ではありますが)。
以下は
vapply
を実行し、期待通りの結果が得られることを確認します。 これは、ちょうど私がPDFスクレイピングをしているときに取り組んでいたことと類似しています。
findD
が
正規表現
を使って生のテキストデータのパターンにマッチさせます (例えば、リストが
split
というリストがあり、各エンティティ内の住所に一致する正規表現がありました。 時々、PDF が順番通りに変換されず、1 つのエンティティに 2 つのアドレスが存在することがあり、それが悪さの原因となっていました)。
> input1 <- list( letters[1:5], letters[3:12], letters[c(5,2,4,7,1)] )
> input2 <- list( letters[1:5], letters[3:12], letters[c(2,5,4,7,15,4)] )
> findD <- function(x) x[x=="d"]
> sapply(input1, findD )
[1] "d" "d" "d"
> sapply(input2, findD )
[[1]]
[1] "d"
[[2]]
[1] "d"
[[3]]
[1] "d" "d"
> vapply(input1, findD, "" )
[1] "d" "d" "d"
> vapply(input2, findD, "" )
Error in vapply(input2, findD, "") : values must be length 1,
but FUN(X[[3]]) result is length 2
input2の3番目の要素にdが2つあるので、vapplyはエラーを発生させます。 しかし、sapplyは出力のクラスを文字ベクトルからリストに変更するので、下流のコードを破壊する可能性があります。
私は学生たちに、プログラマーになることの一部は、「エラーは迷惑だ」という考え方から「エラーは友達だ」という考え方に変えることだと言っています。
ゼロ長入力
関連する点として、入力の長さがゼロの場合は
sapply
は入力の型に関係なく常に空のリストを返すということです。 比較してみてください。
sapply(1:5, identity)
## [1] 1 2 3 4 5
sapply(integer(), identity)
## list()
vapply(1:5, identity, integer(1))
## [1] 1 2 3 4 5
vapply(integer(), identity, integer(1))
## integer(0)
とは
vapply
を使えば、特定の種類の出力が保証されるので、長さが0の入力に対する余分なチェックを書く必要はない。
ベンチマーク
vapply
は、結果を受け取るべき形式をすでに知っているので、少し速くなります。
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx) # autoplot.microbenchmark is moving to the microbenchmark package in the next release so this should be unnecessary soon
autoplot(m)
<イグ
関連
-
二項演算子への非数値引数を報告するR言語エラー
-
[解決済み] Rで文字列から文字を削除する
-
[解決済み] xkcd風のグラフを作るには?
-
[解決済み] なぜ `[`] は `subset` よりも優れているのですか?
-
[解決済み] ベクトル中のある要素のインデックスを求めるR関数はありますか?
-
[解決済み] Rでオブジェクト(変数)が定義されているかどうかを確認するには?
-
[解決済み] [解答】なぜこれらの数字は等しくないのですか?
-
[解決済み] データフレームのカラムのデータ型を決定する
-
[解決済み] 2つの単語の最初の文字を大文字にします。
-
[解決済み] Rのapplyファミリーは構文上の砂糖以上のものなのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
二項演算子への非数値引数を報告するR言語エラー
-
R言語です。「接続を開くことができません」解決策
-
R言語のエラーメッセージと関連する解決策
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました
-
R - ユークリッド距離の計算を簡単にする方法
-
[解決済み] Rでcは何をするのですか?重複] [重複
-
[解決済み] グループ化関数(tapply、by、aggregate)と*applyファミリ
-
[解決済み] ggplotで凡例のタイトルを変更する方法
-
[解決済み】ifelse()でDateオブジェクトがnumericオブジェクトにならないようにする方法
-
[解決済み] セッションが作成されません。このバージョンのChromeDriverはChromeバージョンにしか対応していません ChromeDriver ChromeでSeleniumを使用した場合の74エラー