对内部使用 grepl 的 vapply 函数感到困惑(datacamp 课程的一部分)

Confused by a vapply function using grepl internally (Part of datacamp course)

hits <- vapply(titles,
           FUN = grepl,
           FUN.VALUE = logical(length(pass_names)),
           pass_names)

titles 是一个带有标题的向量,例如 "mr"pass_names 是一个名称列表。

2 个问题。

  1. 我不明白结果矩阵命中
  2. 我不明白为什么最后一行是 pass_names,也不明白我应该如何了解这 4 个参数。在 ?vapply 下,它指定了 x、FUNFUN.VALUE,但我无法弄清楚我应该如何弄清楚 pass_names 需要在那里列出。

我在网上查了,找不到答案,所以我希望这对其他人也有帮助。预先感谢您的回答,是的,我是初学者。


额外信息:本题使用R中的titanic包,pass_names就是titanic$Nametitles就是paste(",", c("Mr\.", "Master", "Don", "Rev", "Dr\.", "Major", "Sir", "Col", "Capt", "Jonkheer"))

你有点困惑是对的。

您问题中的 vapply 代码块等同于:

hits <- vapply(titles,
               FUN = function(x) grepl(x, pass_names),
               FUN.VALUE = logical(length(pass_names)))

vapply 接受一个 ... 参数,该参数接受与提供的参数一样多的参数。如果参数未命名(参见@Roland 的注释),则 ... 位置的第 n 个参数传递给 FUN 的第 n+1 个参数([=15 的第一个参数=] 是 X titles 在这种情况下)。

生成的矩阵的行数与 titanic 中的行数相同,并且有 10 列,长度为 titles。如果第 ipass_names 匹配 titles、[=27] 中的第 j 个正则表达式,则第 [i, j] 个条目为 TRUE =] 如果没有。

本质上,您在 vapply 中传递了两个向量,这相当于两个嵌套的 for 循环。然后将每个配对传递给 grepl 所需的参数:grepl(pattern, x)

具体来说,在 vapply 的第一个循环中,titles 中的第一项与 pass_names[=49 中的每一项进行比较=].然后在第二个循环中,titles 中的第二个项目再次与 pass_names 中的所有项目进行比较,依此类推,直到第一个向量,titles,累死了。

为了说明,您可以使用嵌套 for 循环等效地构建一个 hits2 矩阵,完全按照您的 vapply 输出呈现,hits:

hits2 <- matrix(NA, nrow=length(df$name), ncol=length(titles))
colnames(hits2) <- titles

for (i in seq_along(df$name)) {

  for (j in seq_along(titles)) {

    hits2[i, j] <- grepl(pattern=titles[j], x=df$name[i])

  }

}

all.equal(hits, hits2)
# [1] TRUE

或者,您可以 运行 在 sapply 中与 sapplyvapplylapply 的包装器。但是,vapply 更受欢迎,因为您主动断言输出,而 sapply 根据功能呈现一种方式。例如,在 vapply 中,您可以渲染一个整数矩阵:FUN.VALUE = integer(length(pass_names)).

hits3 <- sapply(titles, FUN = grepl, pass_names)

all.equal(hits, hits3)
# [1] TRUE

总而言之,apply 系列是 运行 迭代和呈现数据结构的更简洁、紧凑的方法,而不是初始化和分配 vector/matrix 与 forwhile 循环。

要进一步阅读,请考虑这个有趣的 SO post: