Как уже было отмечено, vapplyвыполняет две функции:
- Небольшое улучшение скорости
- Повышает согласованность за счет предоставления ограниченных проверок типа возвращаемого значения.
Второй момент - большее преимущество, так как он помогает выявлять ошибки до того, как они произойдут, и приводит к более надежному коду. Эта проверка возвращаемого значения может выполняться отдельно, используя, sapplyа затем stopifnotследует, чтобы убедиться, что возвращаемые значения соответствуют ожидаемым, но vapplyэто немного проще (если более ограничено, поскольку пользовательский код проверки ошибок может проверять значения в пределах границ и т. Д. ).
Вот пример того, как добиться vapplyожидаемого результата. Это похоже на то, над чем я только что работал при парсинге PDF, где можно findDбыло бы использоватьрегулярное выражениедля соответствия шаблону в необработанных текстовых данных (например, у меня был бы список, splitсостоящий из объектов, и регулярное выражение для сопоставления адресов внутри каждого объекта. Иногда PDF-файл конвертировался не по порядку, и для одного сущность, причинившая вред).
> 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
Как я говорю своим студентам, часть того, чтобы стать программистом, - это изменить ваше мышление с «ошибки раздражают» на «ошибки - мой друг».
Входы с нулевой длиной.
Один связанный с этим момент заключается в том, что если длина входных данных равна нулю, sapplyвсегда будет возвращаться пустой список, независимо от типа ввода. Сравните:
sapply(1:5, identity)
sapply(integer(), identity)
vapply(1:5, identity)
vapply(integer(), identity)
С vapply, вы гарантированно получите определенный тип вывода, поэтому вам не нужно писать дополнительные проверки для входов нулевой длины.
Контрольные точки
vapply может быть немного быстрее, потому что он уже знает, в каком формате следует ожидать результатов.
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx)
autoplot(m)
