感谢您的时间。
这可能是我忽略的一个明显问题,但是今天早上我使用dplyr::filter()
遇到了一些意外行为。
使用filter()
似乎可以工作,除非列名和对象名相等。有关详细信息,请参见下面的示例。
我期望data
仅返回data$year
匹配year
或data$month
匹配month
的行,但是它将返回所有值。
我之前已经做过很多次相同的操作,所以我不确定为什么这次会发生这种情况。
将month
重命名为month_by_a_different_name
时,一切正常。有任何想法吗?感谢您的宝贵时间。
library(tidyverse)
# Example data
data <-
tibble(
year = c(2019, 2018, 2017),
month = c("January", "February", "March"),
value = c(1, 2, 3)
)
# -----------------------------------------------
# Values to filter by
year <- 2019
month <- "February"
# Assigning year and month to a different object name
year_by_a_different_name <- year
month_by_a_different_name <- month
# -----------------------------------------------
# Filtering using year and month doesn't work
data %>%
dplyr::filter(year == year) # Doesn't work
data %>%
dplyr::filter(month == month) # Doesn't work
# -----------------------------------------------
# Filtering using different names works
data %>%
filter(year == year_by_a_different_name) # Works
data %>%
filter(month == month_by_a_different_name) # Works
# -----------------------------------------------
# Using str_detect() also doesn't work for month
data %>%
dplyr::filter(str_detect(month, month))
# -----------------------------------------------
# Works with base R
data[data$month == month, ]
data[data$year == year, ]
# -----------------------------------------------
# Objects are of same class
class(data$year) == class(year) # TRUE
class(data$month) == class(month) # TRUE
答案 0 :(得分:4)
TLDR:使用filter(year == !!year)
这是由dplyr的非标准评估(NSE)引起的-无论是引用df$year
还是外部变量year
,这都是不明确的。
NSE使用所谓的“ quosures”来推断,当您在LHS上写year
时,是指管道输入列的列。这种引用技巧使您可以引用tidyverse系列软件包中管道输入范围(即数据框列)中定义的名称,并通过(i)避免键入引号来使您的工作更加轻松到处都有标记;(ii)允许Rstudio为您提供自动完成建议。
但是,在您的情况下,RHS上的year
旨在引用输入data.frame之外的内容,即使此处也使用了该名称。在这种情况下,!!
(“ bangbang”)运算符告诉NSE,您的变量不应加引号,而应按原样进行评估。
您可以在此处找到更多信息:https://dplyr.tidyverse.org/articles/programming.html,尤其是“不同表达式”部分。在上方的小插图中:
在dplyr中(通常在tidyeval中)使用!!表示您希望取消对输入的引用,以便对其进行评估而不是引用。这给了我们一个功能,该功能实际上可以实现我们想要的功能。
答案 1 :(得分:3)
要在原始环境中评估表达式,您可以知道以下定义的位置,这一点都不漂亮。
data %>%
dplyr::filter(year == !!.GlobalEnv$year)
或者您可以使用enquo
。
data %>%
dplyr::filter(month == !!enquo(month))
从帮助页面help('enquo')
。
捕获表示形式
quo()
和enquo()
与它们的expr
类似,但可以捕获 表达式和其环境都在称为quosure的对象中。 该包装器包含对原始环境的引用, 那个表情被捕获了。跟踪环境 表达式很重要,因为这是函数和对象的所在 表达式中提到的已定义。象是可以用
eval_tidy()
求值的对象,就像 符号或函数调用。因为他们总是在他们的评价 原始环境可以看作是允许 表达式从一个函数传到另一个函数,但是回传 评估后立即恢复到原始环境。