根据变量的成对组合过滤数据框

时间:2017-07-05 19:12:56

标签: r dplyr tidyverse

我在下面的示例中有一个数据框ex_data,其中列出了参与者ID,组标识符和一些值。然后,我有第二个数据框,指示需要删除的特定观察(在下面的示例中为remove_data)。有没有办法使用 dplyr 或其他 tidyverse 函数来过滤掉这些组合?在下面的努力中,我最终过滤掉所指示参与者的所有记录,而不仅仅是参与者在该特定组中的数据。我能够使用for循环获得所需的输出,我也将其作为参考。


library(tidyverse)
#> Loading tidyverse: ggplot2
#> Loading tidyverse: tibble
#> Loading tidyverse: tidyr
#> Loading tidyverse: readr
#> Loading tidyverse: purrr
#> Loading tidyverse: dplyr
#> Conflicts with tidy packages ----------------------------------------------
#> filter(): dplyr, stats
#> lag():    dplyr, stats

set.seed(1234)
ex_data <- data_frame(
  id = rep(sample(1:100, 10), 2),
  group = rep(c("a", "b"), each = 10),
  score = rnorm(20)
)
ex_data
#> # A tibble: 20 x 3
#>       id group       score
#>    <int> <chr>       <dbl>
#>  1    12     a  0.50605589
#>  2    62     a -0.57473996
#>  3    60     a -0.54663186
#>  4    61     a -0.56445200
#>  5    83     a -0.89003783
#>  6    97     a -0.47719270
#>  7     1     a -0.99838644
#>  8    22     a -0.77625389
#>  9    99     a  0.06445882
#> 10    47     a  0.95949406
#> 11    12     b -0.11028549
#> 12    62     b -0.51100951
#> 13    60     b -0.91119542
#> 14    61     b -0.83717168
#> 15    83     b  2.41583518
#> 16    97     b  0.13408822
#> 17     1     b -0.49068590
#> 18    22     b -0.44054787
#> 19    99     b  0.45958944
#> 20    47     b -0.69372025


remove_data <- data_frame(
  id = sample(ex_data$id, 3),
  group = sample(c("a", "b"), 3, replace = TRUE)
)
remove_data
#> # A tibble: 3 x 2
#>      id group
#>   <int> <chr>
#> 1    62     b
#> 2    97     a
#> 3    60     b

# Current efforts
ex_data %>%
  filter(!(id %in% remove_data$id & group %in% remove_data$group))
#> # A tibble: 14 x 3
#>       id group       score
#>    <int> <chr>       <dbl>
#>  1    12     a  0.50605589
#>  2    61     a -0.56445200
#>  3    83     a -0.89003783
#>  4     1     a -0.99838644
#>  5    22     a -0.77625389
#>  6    99     a  0.06445882
#>  7    47     a  0.95949406
#>  8    12     b -0.11028549
#>  9    61     b -0.83717168
#> 10    83     b  2.41583518
#> 11     1     b -0.49068590
#> 12    22     b -0.44054787
#> 13    99     b  0.45958944
#> 14    47     b -0.69372025


# Desired output
for (i in 1:nrow(remove_data)) {
  ex_data <- ex_data %>%
    filter(!(id == remove_data$id[i] & group == remove_data$group[i]))
}
ex_data
#> # A tibble: 17 x 3
#>       id group       score
#>    <int> <chr>       <dbl>
#>  1    12     a  0.50605589
#>  2    62     a -0.57473996
#>  3    60     a -0.54663186
#>  4    61     a -0.56445200
#>  5    83     a -0.89003783
#>  6     1     a -0.99838644
#>  7    22     a -0.77625389
#>  8    99     a  0.06445882
#>  9    47     a  0.95949406
#> 10    12     b -0.11028549
#> 11    61     b -0.83717168
#> 12    83     b  2.41583518
#> 13    97     b  0.13408822
#> 14     1     b -0.49068590
#> 15    22     b -0.44054787
#> 16    99     b  0.45958944
#> 17    47     b -0.69372025

1 个答案:

答案 0 :(得分:4)

为什么不使用anti_join代替filter

dplyr::anti_join(ex_data, remove_data)

Joining, by = c("id", "group")
# A tibble: 17 x 3
      id group       score
   <int> <chr>       <dbl>
 1    47     b -0.69372025
 2    99     b  0.45958944
 3    22     b -0.44054787
 4     1     b -0.49068590
 5    97     b  0.13408822
 6    83     b  2.41583518
 7    61     b -0.83717168
 8    12     b -0.11028549
 9    47     a  0.95949406
10    99     a  0.06445882
11    22     a -0.77625389
12     1     a -0.99838644
13    83     a -0.89003783
14    61     a -0.56445200
15    60     a -0.54663186
16    62     a -0.57473996
17    12     a  0.50605589