`sym()`对tidyeval有什么作用?

时间:2018-11-19 19:57:02

标签: r function dplyr rlang

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

2 个答案:

答案 0 :(得分:2)

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

根据?sym

  

sym()从字符串创建符号,而syms()从字符矢量创建符号列表。

?"!!"

  

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

答案 1 :(得分:2)

答案是肯定的,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 )将始终不返回任何结果,因为string literal "birth_year"永远不等于整数文字19(它隐式地强制转换为字符文字{{1 }})。通过使用"19",您可以有效地将该字符串解析为一个符号,从而迫使sym查看数据帧filter中名为birth_year的列,而不是文字字符串{ {1}}。

相反,您不需要在等式的右边starwars,因为"birth_year"中没有sym()列,并且您对实际字面值19感兴趣。如果您要比较数据框中的两列,则希望在等式的两边都starwars。例如,

19