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
# ...