-->

为什么`vapply`比`sapply`更安全吗?(Why is `vapply` safer th

2019-06-18 02:05发布

该文件说,

vapply类似于sapply ,但有一个预先指定的返回值的类型,所以可以更安全[...]使用。

你能否透露细节,为什么它通常是安全的,也许提供的例子吗?


PS:我知道答案,我已经倾向于避免sapply 。 我只是希望有离开SO所以我可以指出我的同事给它一个很好的答案。 请,没有“阅读手册”的答案。

Answer 1:

正如已经指出的那样, 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)



Answer 2:

涉及额外的击键vapply可以节省您的时间后,调试混乱的结果。 如果你调用该函数可以返回不同的数据类型, vapply当然应该使用。

我想到的一个例子就是sqlQueryRODBC包。 如果有执行查询时出现错误,这个函数返回一个character与信息载体。 因此,举例来说,假设你正在试图遍历表名称的矢量tnames ,然后从每个表中与数字列“NumCol”的最大值:

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

如果所有的表名是有效的,这将导致一个numeric矢量。 但是,如果表名称中的一个发生在数据库中更改和查询失败,结果会被强迫模式character 。 使用vapplyFUN.VALUE=numeric(1)但是,将停在这里的误差,并防止它从什么地方突然出现上下行---或者更糟,根本没有。



Answer 3:

如果你总是希望你的结果是什么特别......例如,逻辑载体。 vapply确保这种情况发生,但sapply并不一定这样做。

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

is.logical(a)
is.logical(b)


文章来源: Why is `vapply` safer than `sapply`?
标签: r apply r-faq