在dplyr中使用过滤器内部过滤器会产生意外结果

时间:2015-01-14 06:52:01

标签: r dplyr

使用R 3.1.2dplyr 0.4.0

我试图在filter内使用filter,这听起来非常简单,我不明白为什么它没有给我我预期的结果。这是我在6个月前写的代码,我相当确定它有用,所以要么因为更新的R版本或dplyr或其他依赖项而停止工作。无论如何,这里有一些简单的代码,它根据在df2中的列上filter找到的条件来过滤来自df1的行。

df1 <- data.frame(x = c("A", "B"), stringsAsFactors = FALSE)
df2 <- data.frame(x = "A", y = TRUE, stringsAsFactors = FALSE)
dplyr::filter(df1, x %in% (dplyr::filter(df2, y)$x))

我希望这会显示df1的第一行,但我会得到

# [1] x
# <0 rows> (or 0-length row.names)

我不知道该怎么做。为什么它返回一个向量和一个空的data.frame?

如果我将过滤器代码分解为两个单独的语句,我得到了我期望的结果

xval <- dplyr::filter(df2, y)$x
dplyr::filter(df1, x %in% xval)

#   x
# 1 A

任何人都可以帮我弄清楚为什么会发生这种行为?我不是说这是一个错误,但我不明白。

1 个答案:

答案 0 :(得分:4)

这是一个有效的问题,为什么你的方法不起作用(显然)。我无法回答这个问题,但我建议采用不同的方法,如上所述,它避免了嵌套函数调用(filter 另一个filter内),IMO,是dplyr的用途:通过易于阅读和理解语法表达,从左到右,从上到下。

因此,对于您的示例,因为您感兴趣的列都被命名为&#34; x&#34;你可以这样做:

filter(df2, y) %>% select(x) %>% inner_join(df1)
  • 按列&#34; y&#34;
  • 过滤df2数据
  • 仅选择列&#34; x&#34;
  • 在公共列上执行带有df1的inner_join(&#34; x&#34;)。 inner_join表示:&#34;返回x中匹配值的所有行,以及x和y中的所有列。&#34;

如果它们不同,例如&#34; z&#34;和&#34; x&#34;你可以使用:

filter(df2, y) %>% select(x) %>% inner_join(df1, by = c("z" = "x"))

正如哈德利在下面的评论中指出的那样,在这里使用semi_join代替inner_join会更安全。文档说:

  

semi_join:返回x中y所有匹配值的所有行,   只保留x中的列。

     

半连接与内连接不同,因为内连接将是   为y的每个匹配行返回一行x,其中半连接将为   永远不要复制x行。

因此,您可以为示例案例做到:

filter(df2, y) %>% select(x) %>% semi_join(df1)