r-"sym()"对tidyval做了什么


library(tidyverse)
input_name <- "birth_year"
input_value <- 19
quo(filter(starwars, !!input_name == !!input_value))       # line 5
quo(filter(starwars, !!sym(input_name) == !!input_value))  # line 6

第5行和第6行之间的区别以及sym()函数的使用?为什么sym()只需要在第6行方程的左侧?

sym()的目的是获取字符串并将其取消引用为符号吗?

第5行

<quosure>
expr: ^filter(data, "birth_year" == 19)
env:  global

第6行

<quosure>
expr: ^filter(data, birth_year == 19)
env:  global

在第一种情况下,不计算列,而是计算字符串。但是,通过转换为symbol并对其求值,它将返回列值。lhs中需要sym,因为我们不是要获取文字值,而是要提取列值

根据?sym

sym((从字符串中创建符号,syms((从字符向量中创建符号列表。

?"!!"

!!运算符取消对其参数的引用。它会立即在周围的环境中进行评估。

答案是肯定的,sym()的目标是获取字符串并将其解析为符号。在等式的左侧需要这个的原因可以在?filter:中看到

...: Logical predicates defined in terms of the variables in
‘.data’. Multiple conditions are combined with ‘&’. Only rows
where the condition evaluates to ‘TRUE’ are kept.

filter( starwars, "birth_year" == 19 )将始终不返回任何结果,因为字符串文字"birth_year"永远不等于整数文字19(在比较中,它被隐式强制为字符文字"19"(。通过使用sym,您可以有效地将该字符串解析为符号,迫使filter查看数据帧starwars中名为birth_year的列,而不是文字字符串"birth_year"

相反,不需要方程右侧的sym(),因为starwars中没有列19,而是对实际的文字值19感兴趣。如果比较数据帧中的两列,则需要相等两边的sym()。例如,

name1 <- "skin_color"
name2 <- "eye_color"
filter( starwars, !!sym(name1) == !!sym(name2) )
# # A tibble: 6 x 13
#   name  height  mass hair_color skin_color eye_color birth_year gender homeworld
#   <chr>  <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr>  <chr>    
# 1 Wick…     88    20 brown      brown      brown              8 male   Endor    
# 2 Jar …    196    66 none       orange     orange            52 male   Naboo    
# 3 Eeth…    171    NA black      brown      brown             NA male   Iridonia 
# 4 Mas …    196    NA none       blue       blue              NA male   Champala 
# ...

最新更新