r - dplyr 0.7.5 select() 行为的变化

标签 r dplyr

使用命名向量指定列时,dplyr 0.7.5 中的 select() 返回与 dplyr 0.7.4 不同的结果。

library(dplyr)                               
df <- data.frame(a = 1:5, b = 6:10, c = 11:15)
print(df)                                     
#>   a  b  c
#> 1 1  6 11
#> 2 2  7 12
#> 3 3  8 13
#> 4 4  9 14
#> 5 5 10 15

# a named vector
cols <- c(x = 'a', y = 'b', z = 'c')          
print(cols)                                   
#>  x   y   z 
#> "a" "b" "c"

# with dplyr 0.7.4
# returns column names with vector values
select(df, cols)                              
#>   a  b  c
#> 1 1  6 11
#> 2 2  7 12
#> 3 3  8 13
#> 4 4  9 14
#> 5 5 10 15

# with dplyr 0.7.5
# returns column names with vector names
select(df, cols)                              
#>   x  y  z
#> 1 1  6 11
#> 2 2  7 12
#> 3 3  8 13
#> 4 4  9 14
#> 5 5 10 15

这是错误还是功能?

最佳答案

IMO 它可能被视为 0.7.4 中的一个错误,现在已修复/更加用户友好。

随着转向tidyselect,逻辑变得更加复杂。 如果将 dplyr::select_vars 与新的 tidyselect::vars_select 进行比较(这些是 dplyr:::select.data.frame 使用的变体> 分别在 0.7.4 和 0.7.5 中),您可以发现下面的行丢失了 0.7.4 中 named "ed (字符串)情况的名称:

ind_list <- map_if(ind_list, is_character, match_var, table = vars)

# example:
dplyr:::select.data.frame(mtcars, c(a = "mpg", b = "disp"))

请注意,这通常不是命名向量的问题,因为典型的不带引号的情况总是没问题:

dplyr:::select.data.frame(mtcars, c(a = mpg, b = disp))
# (here the names are indeed "a" and "b" afterwards)

有一行代码处理c()的使用:

ind_list <- map_if(ind_list, !is_helper, eval_tidy, data = names_list)

eval_tidy 来自 rlang 包,上面的行将针对有问题的调用返回以下内容:

[[1]]
 a      b 
 "mpg" "disp" 
<小时/>

现在使用 tidyselect,我们有一些额外的处理,请参阅 https://github.com/tidyverse/tidyselect/blob/master/R/vars-select.R .

特别是,vars_select_eval 有以下行,它在其中处理 c() 的使用:

ind_list <- map_if(quos, !is_helper, overscope_eval_next, overscope = overscope)

overscope_eval_next 再次来自 rlang 包,并调用与 eval_tidy 相同的例程,但它收到一个 overscope 处理字符串的 c() 变体(通过 overscope 参数)。请参阅tidyselect:::vars_c。 因此,在这一行之后,c(a = "mpg", b = "disp") 的情况与 c(a = mpg, b = disp) 相同:

[[1]]
a b   # these are the names
1 3   # these are the positions of the selected cols

is_character 然后在后续代码中不再有效,这与上面的 rlang::eval_tidy 不同。

如果您在 rlang 中查看这些函数,您会发现 overscope_eval_next 已被软弃用,取而代之的是 eval_tidy,这一事实可能会让您感到困惑以上。但在这里我猜 tidyselect 只是还没有被“清理”(命名不一致等也必须解决,所以它不仅仅是一行的重写)与通话)。但最终 eval_tidy 现在可以以相同的方式使用,并且可能会如此。

关于r - dplyr 0.7.5 select() 行为的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50748239/

相关文章:

R - 三元函数的矢量化实现

r - 分支预测如何影响 R 中的性能?

r - 从 dplyr::mutate 调用用户定义的函数

r - 在 R 中,dplyr 中的 group_by 是如何工作的?

r - 如何在R中计算前几年的运行总计?

r - 命名空间无法在 R 中卸载

r - 使用 dplyr 对数据框中的中位数进行分组

r - 制作线性模型时因子与矢量对象类型的影响

r - 如何访问分组过滤器操作的组 ID?

R- 如何使用包含因不同变量(列)而异的阈值的查找表来替换低于这些阈值的值?