【问题标题】:filter one dataframe via conditions in another通过另一个数据帧中的条件过滤一个数据帧
【发布时间】:2020-04-05 22:25:01
【问题描述】:

我想通过任意数量的条件递归过滤数据帧d(表示为另一个数据帧z中的行)。

我从一个数据框d开始:

d <- data.frame(x = 1:10, y = letters[1:10])

第二个数据框z,具有x1x2 列,它们分别是过滤d$x 的下限和上限。此数据框z 可能会增长到任意行数。

z <- data.frame(x1 = c(1,3,8), x2 = c(1,4,10))

我想返回d 的所有行,其中d$x &lt;= z$x1[i]d$x &gt;= z$x2[i] 用于所有i,其中i = nrow(z)

所以对于这个玩具示例,排除 1:1、3:4、8:10 中的所有内容。

   x  y
2  2  b 
5  5  e
6  6  f
7  7  g

【问题讨论】:

  • 为什么包含x=2?它不符合您的约束条件。
  • 它确实符合约束条件。 z 中的每一行都是一对约束。所以排除 1:1、3:4、8:10 中的所有内容。
  • 那么你的最后一帧是要排除的行吗?抱歉,我一定错过了。
  • 嗯,你说得对。我可以在问题陈述中更清楚地说明这一点。
  • 您所说的是非等值连接,目前(在 R 中)有效地做到这一点的唯一方法是使用 data.table。我认为 akrun 正在努力为您找到一个好的解决方案。

标签: r dplyr tidyverse


【解决方案1】:

我们可以在x1x2 值之间创建一个序列,并使用anti_joind 中选择z 中不存在的行。

library(tidyverse)

remove <- z %>%
  mutate(x = map2(x1, x2, seq)) %>%
  unnest(x) %>%
  select(x)

anti_join(d, remove)

#  x y
#1 2 b
#2 5 e
#3 6 f
#4 7 g

【讨论】:

    【解决方案2】:

    我们可以使用非等连接

    library(data.table)
    i1 <- setDT(d)[z, .I, on = .(x >=x1, x <= x2), by = .EACHI]$I
    i1
    #[1]  1  3  4  8  9 10
    d[i1]
    #    x y
    #1:  1 a
    #2:  3 c
    #3:  4 d
    #4:  8 h
    #5:  9 i
    #6: 10 j
    d[!i1]
    #   x y
    #1: 2 b
    #2: 5 e
    #3: 6 f
    #4: 7 g
    

    或使用fuzzyjoin

    library(fuzzyjoin)
    library(dplyr)
    fuzzy_inner_join(d, z, by = c('x' = 'x1', 'x' = 'x2'),
            match_fun = list(`>=`, `<=`)) %>% 
         select(names(d))
    # A tibble: 6 x 2
    #      x y    
    #  <int> <fct>
    #1     1 a    
    #2     3 c    
    #3     4 d    
    #4     8 h    
    #5     9 i    
    #6    10 j    
    

    或者从 'd' 中获取不在 'x' 中的行

    fuzzy_anti_join(d, z, by = c('x' = 'x1', 'x' = 'x2'),
            match_fun = list(`>=`, `<=`)) %>% 
         select(names(d))
    # A tibble: 4 x 2
    #      x y    
    #  <int> <fct>
    #1     2 b    
    #2     5 e    
    #3     6 f    
    #4     7 g    
    

    【讨论】:

    • 非等值连接方法有效,但模糊连接不能完全返回预期结果。
    • @RichPauloo 我展示了两种方法,它们都对我有用。
    • @RichPauloo 无论如何,如果你只提到基于 tidyverse,可能已经创建了它。时间
    • @RichPauloo 如果你的意思是anti_join,那就是fuzzy_anti_join。无论如何,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多