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()
的目的是接受字符串并将其取消引用成符号吗?
<quosure>
expr: ^filter(data, "birth_year" == 19)
env: global
<quosure>
expr: ^filter(data, birth_year == 19)
env: global
答案 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