vapply は FUN.VALUE のひな形と実際の戻り値の型・長さが違うとエラーになる
vapplyはFUN.VALUEに渡したひな形と、実際に関数が返す値の型や長さが厳密に一致しないとエラーになります。sapplyのように結果の形を黙って合わせてはくれません。
このエラーが出る典型パターン
パターン1
1 nums <- c(1, 2, 3) 2 result <- vapply(nums, function(x) as.character(x), numeric(1) ) ^ 3 print(result)
vapplyは実際の戻り値がnumeric(1)のひな形と型不一致(character)だとその場でエラーにします。
直し方: numeric(1) を character(1) にします。
パターン2
1 labels <- c("a", "b", "c") 2 result <- vapply(labels, function(x) nchar(x), character(1)) ^ 3 print(result)
nchar()は整数を返すのに、ひな形をcharacter(1)にしてしまうと型が一致せずvapplyがエラーになります。
直し方: character(1) を integer(1) にします。
パターン3
1 ids <- c(10, 20, 30) 2 result <- vapply(ids, function(x) c(x, x * 2), numeric(1)) ^ 3 print(result)
関数が長さ2のベクトルを返しているのに、ひな形の長さをnumeric(1)にしてしまうと長さ不一致でエラーになります。
直し方: numeric(1) を numeric(2) にします。
パターン4
1 flags <- c(1, 0, 1) 2 result <- vapply(flags, function(x) x == 1, character(1)) ^ 3 print(result)
x == 1は論理値を返すため、ひな形はlogical(1)である必要があり、character(1)にすると型不一致でエラーになります。
直し方: character(1) を logical(1) にします。
パターン5
1 names_vec <- c("tom", "al") 2 result <- vapply(names_vec, function(x) toupper(x), numeric(1) ) ^ 3 print(result)
toupper()は文字列を返すので、ひな形をnumeric(1)にするとFUN.VALUEとの型不一致でvapplyがエラーを出します。
直し方: numeric(1) を character(1) にします。
よくある誤解
「vapplyもsapplyと同じく、結果の形はうまく合わせてくれるはず」という思い込みは誤りです。vapplyはFUN.VALUEで指定した型・長さを守らせるための関数で、想定と違う値が返るとその場でエラーとして検出します。
実務での勘所
vapplyの厳格さは安全性のためだけではありません。FUN.VALUEで結果の型と長さをあらかじめ教えておくことで、Rは実際にループを回す前に、結果を格納するための領域をちょうど必要な分だけ事前に確保できます。sapplyは結果が出そろうまで最終的な形が分からないため、内部的にはより非効率な組み立て方をしています。vapplyは「安全なだけの、面倒な代替品」ではなく、大きなデータを扱う場面では実行速度の面でも有利な選択肢です。