对内部使用 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 个问题。
- 我不明白结果矩阵命中
- 我不明白为什么最后一行是
pass_names
,也不明白我应该如何了解这 4 个参数。在 ?vapply
下,它指定了 x、FUN
、FUN.VALUE
,但我无法弄清楚我应该如何弄清楚 pass_names
需要在那里列出。
我在网上查了,找不到答案,所以我希望这对其他人也有帮助。预先感谢您的回答,是的,我是初学者。
额外信息:本题使用R中的titanic包,pass_names
就是titanic$Name
,titles
就是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
。如果第 i
个 pass_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
中与 sapply
和 vapply
是 lapply
的包装器。但是,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 与 for
或 while
循环。
要进一步阅读,请考虑这个有趣的 SO post:
hits <- vapply(titles,
FUN = grepl,
FUN.VALUE = logical(length(pass_names)),
pass_names)
titles
是一个带有标题的向量,例如 "mr"
,pass_names
是一个名称列表。
2 个问题。
- 我不明白结果矩阵命中
- 我不明白为什么最后一行是
pass_names
,也不明白我应该如何了解这 4 个参数。在?vapply
下,它指定了 x、FUN
、FUN.VALUE
,但我无法弄清楚我应该如何弄清楚pass_names
需要在那里列出。
我在网上查了,找不到答案,所以我希望这对其他人也有帮助。预先感谢您的回答,是的,我是初学者。
额外信息:本题使用R中的titanic包,pass_names
就是titanic$Name
,titles
就是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
。如果第 i
个 pass_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
中与 sapply
和 vapply
是 lapply
的包装器。但是,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 与 for
或 while
循环。
要进一步阅读,请考虑这个有趣的 SO post: