86

ドキュメントによると

vapplyに似てsapplyいますが、戻り値の型が事前に指定されているため、より安全に [...] 使用できます。

なぜ一般的に安全なのか、例を挙げて詳しく教えてください。


PS: 私は答えを知っており、すでに回避する傾向がありsapplyます。ここSOに素敵な答えがあればいいのにと思います。そうすれば、同僚にそれを示すことができます。「マニュアルを読んでください」という答えはありません。

4

3 に答える 3

75

すでに述べたように、vapplyは次の 2 つのことを行います。

  • わずかな速度向上
  • 戻り値の型チェックを制限することで、一貫性を向上させます。

2 番目の点は、エラーが発生する前にキャッチするのに役立ち、より堅牢なコードにつながるため、より大きな利点です。sapplyこの戻り値のチェックは、後に続くを使用stopifnotして、戻り値が期待したものと一致していることを確認することで個別に行うことができますvapplyが、少し簡単です (カスタムエラーチェックコードが境界内の値をチェックできるため、より制限されている場合など. )。

vapply結果が期待どおりであることを確認する例を次に示します。これは、生のテキスト データのパターンを照合するためにfindDを使用するPDF スクレイピング中に取り組んでいたものと類似しています (たとえば、エンティティごとのリストと、各エンティティ内のアドレスを照合するための正規表現があります。 PDF が順不同で変換され、エンティティのアドレスが 2 つになり、問題が発生しました)。split

> 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 番目の要素に 2 つの d があるため、vapply はエラーを生成します。ただし、sapply は出力のクラスを文字ベクトルからリストに変更するため、下流のコードが壊れる可能性があります。

私が生徒たちに言っているように、プログラマーになることの一部は、「エラーは迷惑だ」から「エラーは友達だ」という考え方に変わることです。

ゼロ長の入力
関連するポイントの 1 つは、入力の長さがゼロの場合、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すると、特定のタイプの出力が保証されるため、長さゼロの入力に対して追加のチェックを記述する必要はありません。

ベンチマーク

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)

自動プロット

于 2012-09-09T16:41:48.843 に答える
15

に含まれる追加のキー ストロークvapplyにより、後で紛らわしい結果をデバッグする時間を節約できます。呼び出している関数が異なるデータ型を返す可能性がある場合は、vapply必ず使用する必要があります。

頭に浮かぶ1つの例sqlQueryは、RODBCパッケージにあります。クエリの実行中にエラーが発生した場合、この関数はcharacterメッセージを含むベクターを返します。たとえば、テーブル名のベクトルを反復処理し、tnames各テーブルの数値列 'NumCol' から最大値を選択しようとしているとします。

sapply(tnames, 
   function(tname) sqlQuery(cnxn, paste("SELECT MAX(NumCol) FROM", tname))[[1]])

すべてのテーブル名が有効な場合、これはnumericベクトルになります。ただし、データベースでテーブル名の 1 つが変更され、クエリが失敗した場合、結果はモードに強制されますcharactervapplyただし、 withを使用するとFUN.VALUE=numeric(1)、ここでエラーが停止し、どこかでエラーが発生するのを防ぐことができます。さらに悪いことに、まったく発生しません。

于 2012-09-09T18:05:47.700 に答える
13

結果を常に特定のものにしたい場合...たとえば、論理ベクトル。 vapplyこれが確実sapplyに行われるようにしますが、必ずしもそうするとは限りません。

a<-vapply(NULL, is.factor, FUN.VALUE=logical(1))
b<-sapply(NULL, is.factor)

is.logical(a)
is.logical(b)
于 2012-09-09T15:29:11.503 に答える