"tidyselect“包提供了一个选择助手函数where。where用于通过自定义函数选择数据框列。它是来自"tidyselect“的一个内部函数。这意味着where不会加载到您的名称空间,您只能通过tidyselect:::where调用它。
但是,我在dplyr vignettes: columnwise operations中看到了以下示例。
starwars %>%
summarise(across(where(is.character), ~ length(unique(.x))))
#> # A tibble: 1 x 8
#> name hair_color skin_color eye_color sex gender homeworld species
#> <int> <int> <int> <int> <int> <int> <int> <int>
#> 1 87 13 31 15 5 3 49 38在本例中,where是在没有前缀“tidyselect:”的情况下编写的,但很明显,代码中没有错误,它会产生有意义的结果。这对我来说似乎很奇怪。我想知道代码为什么能正常工作。
我猜这是由于“代码引用”,这是tidyeval方法的一部分。粗略地说,代码引用将代码作为表达式挂起,并在稍后的“内部环境”中计算表达式。这只是一个直观的猜测,我不知道如何测试它。
我希望有人能帮助我解决“在哪里”的问题,或者留下一些关于代码如何为我工作的参考。
发布于 2020-11-13 15:09:01
您没有说在示例中附加了哪些包,但让我们假设唯一附加的包是dplyr。
library(dplyr)首先,我们注意到函数where未附加,即不为当前R会话所知。我们只需在控制台中键入其名称(不带括号)即可进行检查。如果函数是附加的,我们现在可以看到它的源代码。相反,我们得到一个错误,即找不到对象where。
但是,我们注意到dplyr附加了来自tidyselect的其他函数,starts_with就是一个例子。如果我们重复在控制台中输入名称的实验,我们现在可以看到源代码,还可以看到函数源自tidyselect命名空间:
> starts_with
function (match, ignore.case = TRUE, vars = NULL)
{
check_match(match)
vars <- vars %||% peek_vars(fn = "starts_with")
if (ignore.case) {
vars <- tolower(vars)
match <- tolower(match)
}
flat_map_int(match, starts_with_impl, vars)
}
<bytecode: 0x0000027338e5f8e8>
<environment: namespace:tidyselect>在本例中,dplyr使用NAMESPACE文件附加了函数starts_with,您可以在该文件中列出其他包中的函数,这些函数应该与您的包一起附加。您可以在dplyr source code中签入。
但是,正如我们已经看到的,where不是以这种方式提供的。在这种情况下,函数确实被引用,并且仅在tidyselect包中求值。如果查看source code for across,您会注意到在第82行,列规范被传递给在同一文件中定义的函数across_setup。在此函数中,列规范被引用(第174、175行),然后发送到tidyselect函数tidyselect::eval_select (第177行)。这个函数是tidyselect包的一部分,可以访问where。
https://stackoverflow.com/questions/64816536
复制相似问题