内部使用grepl的vapply函数混淆(数据广告课程的一部分)

时间:2018-02-13 14:03:20

标签: r apply lapply sapply grepl

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

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

2个问题。

  1. 我不明白生成的矩阵命中
  2. 我不明白为什么最后一行是pass_names,也不知道我应该怎么知道这四个论点。在?vapply下,它特定于x,FUNFUN.VALUE,但我无法弄清楚我应该如何确定pass_names需要列在那里。
  3. 我看过网上找不到答案,所以我希望这对其他人也有所帮助。提前感谢您的回答,是的,我是初学者。

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

2 个答案:

答案 0 :(得分:1)

你有点困惑。

您问题中的vapply代码块相当于:

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

vapply采用...参数,该参数采用所提供的参数。如果参数未命名(参见@Roland的注释),...位置的第n个参数将传递给FUN的第n + 1个参数({{1}的第一个参数在这种情况下,{}是FUN X

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

答案 1 :(得分:0)

基本上你在vapply中传递两个向量,相当于两个嵌套的for循环。然后将每个配对传递到grepl:grepl(pattern, x)的必需参数中。

具体而言,在vapply的第一个循环中, titles 中的第一项与 pass_names 的每个项目进行比较。然后在第二个循环中, titles 中的第二个项目再次与 pass_names 的所有项目进行比较,依此类推,直到第一个向量 titles 用尽

为了说明,您可以使用嵌套的for循环等效地构建 hits2 矩阵,完全呈现为您的vapply输出,命中

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中运行完全相同但没有必需的 FUN.VALUE 参数,因为sapplyvapply都是lapply的包装器}。但是,vapply更为首选,因为您主动断言输出,sapply根据功能呈现一种方式。例如,在vapply中,您可以使用:FUN.VALUE = integer(length(pass_names))呈现整数矩阵。

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

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

总而言之, apply 系列是更简洁,更紧凑的方式来运行迭代并呈现数据结构,而不是初始化和分配带有for或{{1的向量/矩阵循环。

如需进一步阅读,请考虑这个有趣的SO帖子:Is the “*apply” family really not vectorized?