使用vapply而不是sapply

时间:2017-04-19 19:11:09

标签: r sapply

我正在http://adv-r.had.co.nz/Functionals.html阅读Hadley的Advanced R。他谈到了sapplyvapply之间的区别。我的问题与使用vapply代替sapply有关,在他的例子中他没有进一步讨论。

这是他的代码:

df2 <- data.frame(x = 1:10, y = Sys.time() + 1:10)
sapply(df2, class)

返回

$x
[1] "integer"

$y
[1] "POSIXct" "POSIXt"

但是,当我运行vapply时,我收到错误消息。

vapply(df2, class, character(1))

错误:

Error in vapply(df2, class, character(1)) : values must be length 1,
 but FUN(X[[2]]) result is length 2

我有两个问题:

问题:1)当我用字符(2)替换字符(1)时,它会给我以下错误消息:

vapply(df2, class, character(2))
Error in vapply(df2, class, character(2)) : values must be length 2,
 but FUN(X[[1]]) result is length 1

为什么会这样?

问题:2)如何使用vapply代替sapply

我正在学习R所以你的答案将帮助我更深入地理解R.我很感激你的想法。

1 个答案:

答案 0 :(得分:4)

问题1:

character(2)的错误是因为字符向量"integer"的长度仅为1,并且正确地不能对长度为2的字符向量的预期结果进行一致性检查。

问题2:

vapply()作为safer version of sapply()存在,因为它确保您只返回对FUN的每个应用程序的期望。我猜也更安全,因为vapply()的输出是一致的 - 你不会得到一个向量,一个矩阵或一个列表。您将获得长度为1的返回子组件的向量,否则为一个数组。

在您提供的具体示例中,您无法使用vapply(),因为class返回的内容并非一致。如果调用vapply()的输出与预期不符,您必须知道或预期某些输出会FUN失败。

在这种情况下,我想你可以做到

df2 <- data.frame(x = 1:10, y = Sys.time() + 1:10)
vapply(df2, FUN = function(x) paste(class(x), collapse = "; "),
       FUN.VALUE = character(1))

> vapply(df2, FUN = function(x) paste(class(x), collapse = "; "),
+        FUN.VALUE = character(1))
                x                 y 
        "integer" "POSIXct; POSIXt"

但是否对你有用是另一回事。

真的,使用vapply()归结为知道FUN会发生什么,并希望只获得该输出。如果您不知道或无法控制它,那么lapply()可能会更好。