Почему "vapply" безопаснее, чем "sapply"?
в документации написано
vapplyпохож наsapply, но и предварительно указанный тип возвращаемого значения, поэтому он может быть безопаснее...] пустить в ход.
не могли бы Вы уточнить, почему это, как правило, безопаснее, возможно, приводя примеры?
P. S.: Я знаю ответ и я уже стремятся избежать sapply. Я просто хочу, чтобы здесь был хороший ответ, чтобы я мог указать на него своим коллегам. Пожалуйста, нет " прочитайте инструкцию" ответ.
3 ответов:
как уже отмечалось,
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) ## [1] 1 2 3 4 5 sapply(integer(), identity) ## list() vapply(1:5, identity) ## [1] 1 2 3 4 5 vapply(integer(), identity) ## 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)
дополнительные ключевые штрихи, связанные с
vapplyможет сэкономить вам время отладки запутанных результатов позже. Если вызываемая функция может возвращать различные типы данных,vapplyбезусловно, следует использовать.один из примеров, который приходит на ум, будет
sqlQueryнаRODBCпакета. Если есть ошибка выполнения запроса, эта функция возвращаетcharacterвектор с сообщением. Так, например, предположим, что вы пытаетесь перебрать вектор имен таблицtnamesи выбираем максимальное значение из числового столбца 'NumCol' в каждой таблице с:sapply(tnames, function(tname) sqlQuery(cnxn, paste("SELECT MAX(NumCol) FROM", tname))[[1]])если все имена таблиц действительны, это приведет к
numericвектор. Но если одно из имен таблиц изменится в базе данных и запрос завершится неудачно, результаты будут принудительно переведены в режимcharacter. ИспользуяvapplyСFUN.VALUE=numeric(1), однако, остановит ошибку здесь и предотвратит ее появление где-то вниз по линии-- - или, что еще хуже, совсем нет.
Если вы всегда хотите, чтобы ваш результат был чем-то особенным...например, логический вектор.
vapplyгарантирует, что это произойдет, ноsapplyне обязательно это делать.a<-vapply(NULL, is.factor, FUN.VALUE=logical(1)) b<-sapply(NULL, is.factor) is.logical(a) is.logical(b)

Comments