dplyr::filter() 的意外行为

Eth*_*ker 4 r filter dplyr tidyverse

谢谢你的时间。

这可能是我忽略的一个明显问题,但今天早上我使用dplyr::filter().

使用filter()似乎有效,除非列名和对象名相同。有关详细信息,请参阅下面的示例。

我期望只返回matches或matches 的data行,但它会返回所有值。 data$yearyeardata$monthmonth

我之前已经做过很多次同样的操作,所以我不确定为什么这次会发生这种情况。

重命名为 时monthmonth_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
Run Code Online (Sandbox Code Playgroud)

hdk*_*rgr 5

总而言之:使用filter(year == !!year)

\n\n

这是由 dplyr 的非标准评估 (NSE) 引起的 - 无论您指的是df$year还是外部变量,它都是不明确的year。\nNSE 使用所谓的“quosures”来推断当您year在 LHS 上写入时,您指的是管道输入列的列。这种引用技巧允许您引用 tidyverse 系列包中管道输入范围(即数据框列)中定义的名称,并且通过 (i) 避免键入引用,使您的生活变得更加轻松 -到处都有标记,并且 (ii) 允许 Rstudio 为您提供自动完成建议。

\n\n

但是,在您的情况下,year在 RHS 上意味着引用输入 data.frame 之外的内容,即使该名称也在那里使用。在这种情况下,!!(“bangbang”) 运算符告诉 NSE 您的变量不应被引用,而应按原样求值。

\n\n

您可以在这里找到更多信息:https://dplyr.tidyverse.org/articles/programming.html,特别是“不同表达式”部分。从上面的小插图:

\n\n
\n

在 dplyr (以及一般的 tidyeval)中,您使用 !! 表示您想要取消引用输入,以便对其\xe2\x80\x99 进行评估,而不是引用。这为我们提供了一个实际上可以完成我们想要的功能的函数。

\n
\n