dplyr 0.7.5更改select()行为

Eva*_*rth 13 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
Run Code Online (Sandbox Code Playgroud)

这是一个错误还是一个功能?

Rol*_*ASc 1

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

随着转移到tidyselect,逻辑变得更加复杂了。如果dplyr::select_vars与新版本tidyselect::vars_select(这些分别是 0.7.4 和 0.7.5 中使用的变体)进行比较,您会发现下面的行丢失了 0.7.4 中命名和引用dplyr:::select.data.frame(字符串)情况的名称:

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

# example:
dplyr:::select.data.frame(mtcars, c(a = "mpg", b = "disp"))
Run Code Online (Sandbox Code Playgroud)

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

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

有一行代码处理以下用法c()

ind_list <- map_if(ind_list, !is_helper, eval_tidy, data = names_list)
Run Code Online (Sandbox Code Playgroud)

eval_tidy来自rlang包,并且在上面的行中将为有问题的调用返回以下内容:

[[1]]
 a      b 
 "mpg" "disp" 
Run Code Online (Sandbox Code Playgroud)

现在有了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)
Run Code Online (Sandbox Code Playgroud)

overscope_eval_next再次来自rlang包并调用相同的例程eval_tidy,但它接收处理字符串的超出范围的变体(通过参数)。看。因此,在这一行之后,情况变得与以下内容相同:c()overscopetidyselect:::vars_cc(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
Run Code Online (Sandbox Code Playgroud)

is_characterthen 在后续代码中不再成立,与上面的rlang::eval_tidy.

如果您查看 中的这些函数,考虑到上述情况,软弃用并支持 的rlang事实可能会让您感到困惑。但在这里我猜想这还没有被“清理”(命名不一致等问题也必须得到解决,所以它不仅仅是对调用的一行进行重写)。但最终现在可以以同样的方式使用,并且可能会如此。overscope_eval_nexteval_tidytidyselecteval_tidy