通过另一个条件过滤一个数据框

时间:2020-04-05 22:25:01

标签: r dplyr tidyverse

我想通过任意数量的条件(表示为另一个数据帧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 <= z$x1[i]d$x >= z$x2[i]的所有行,其中i

因此,对于这个玩具示例,请排除1:1、3:4、8:10(包括1和2)中的所有内容。

i = nrow(z)

2 个答案:

答案 0 :(得分:1)

我们可以使用非等额联接

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    

答案 1 :(得分: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