r语言 - 为什么可以在 dplyr 辅助函数"across"中检测到 tidyselect 帮助程序函数"where"?



;tidyselect";包提供了一个选择助手函数CCD_ 1。where用于选择具有自定义功能的数据帧列。它是来自";tidyselect";。这意味着where不会加载到您的命名空间中,您只能通过tidyselect:::where调用它。

然而,我从dplyr的小插曲中看到了以下示例:列操作。

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是在没有前缀"0"的情况下编写的;tidyselect:::"但很明显,代码中并没有错误,它产生了有意义的结果。这对我来说似乎很奇怪。我想知道为什么代码运行正常。

我想这是由于";代码引用";,这是tidyval方法论的一部分。粗略地说,代码引用将代码挂起作为表达式,并稍后在"中对表达式求值;内部环境";。这只是一个直观的猜测,我不知道如何测试它

我希望有人能帮助我;其中";问题,或者给我留下一些关于代码如何工作的参考。

您没有说明示例中附加了哪些包,但假设唯一附加的包是dplyr

library(dplyr)

首先,我们注意到函数where没有被附加,即当前R会话不知道。我们只需在控制台中键入其名称(不带括号(即可进行检查。如果附加了函数,我们现在可以看到它的源代码。相反,我们得到一个错误,即找不到对象where

然而,我们注意到dplyr附加了where0的其他函数,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>

在这种情况下,函数starts_with是由dplyr使用NAMESPACE文件附加的,在该文件中,您可以列出应该与包一起附加的其他包中的函数。您可以签入dplyr源代码。

但是where并没有像我们已经看到的那样以这种方式提供。在这种情况下,函数确实被引用,并且仅在tidyselect包中进行评估。如果查看cross的源代码,您会注意到在第82行中,列规范被传递到同一文件中定义的函数across_setup。在该函数中,列规范被引用(第174175行(,然后发送到tidyselect函数tidyselect::eval_select(第177行(。该函数是tidyselect包的一部分,可以访问where

最新更新