【问题标题】:filtering using the common values between two columns using dplyr使用 dplyr 使用两列之间的公共值进行过滤
【发布时间】:2021-06-23 14:40:21
【问题描述】:

我有一个这样的数据集 -

tibble(
  year = c (2005, 2005, 2005,
            2006, 2006, 2006,
            2007,2007,2007),
  var1 = c (2136,2136,2136,
            2285,2285,2285,
            2968,2968,2968),
  var2 = c (125860,1318,127464,
            8972,2136,5046,
            4739,1619,10063)
)

我想像这样过滤数据集 - 首先按变量yearvar1 对数据进行分组,然后比较列var1var2, 如果发现var1var2列中的值匹配,那么我想过滤所有它们。

对于示例数据集,如果我们查看,我们可以看到 2005 年的 var1 2136 与 2006 年的 var2 中的 2136 匹配。因此,我想过滤 2005 年和 2006 年的行,因为在这两列中 @987654331 @ 和 var2,它们有一个共同的值 - 2136。

所以预期的结果将如下所示 -

tibble(
  year = c (2005, 2005, 2005,
            2006, 2006, 2006
            ),
  var1 = c (2136,2136,2136,
            2285,2285,2285),
  var2 = c (125860,1318,127464,
            8972,2136,5046)
)

有人可以帮忙吗?

【问题讨论】:

  • 您想通过yearvar1 分组来完成什么?我认为这可以满足您的需求:df %>% filter(!var1 %in% var2)
  • 如果其中一个答案解决了您的问题,请accept it;这样做不仅为回答者提供了一些积分,而且还为有类似问题的读者提供了一些关闭。尽管您只能接受一个答案,但您可以选择对您认为有帮助的人进行投票。 (如果仍有问题,您可能需要编辑您的问题并提供更多详细信息。)

标签: r dplyr


【解决方案1】:

在 tidyverse 中相当容易。我在这里使用purrr::map2_lgl() 除了通常的 dplyr 函数。

library(tidyverse)
df <- tibble(
  year = c (2005, 2005, 2005,
            2006, 2006, 2006,
            2007,2007,2007),
  var1 = c (2136,2136,2136,
            2285,2285,2285,
            2968,2968,2968),
  var2 = c (125860,1318,127464,
            8972,2136,5046,
            4739,1619,10063)
)

df %>% 
  mutate(xx = map2_lgl(var1, var2, ~ .x %in% var2 | .y %in% var1)) %>%
  group_by(year, var1) %>%
  filter(any(xx))
#> # A tibble: 6 x 4
#> # Groups:   year, var1 [2]
#>    year  var1   var2 xx   
#>   <dbl> <dbl>  <dbl> <lgl>
#> 1  2005  2136 125860 TRUE 
#> 2  2005  2136   1318 TRUE 
#> 3  2005  2136 127464 TRUE 
#> 4  2006  2285   8972 FALSE
#> 5  2006  2285   2136 TRUE 
#> 6  2006  2285   5046 FALSE

reprex package (v2.0.0) 于 2021 年 6 月 23 日创建

如果需要,您可以在取消分组后删除 xx。我保留这个是为了解释。

【讨论】:

  • 实际上它适用于这个示例问题,但对于大型数据集,它给出的答案与我想要的不匹配。任何的想法?我认为一开始将数据集按yearvar1 分组很重要,然后可以应用其他功能。
  • 不,在开头分组不会产生正确的结果。你能找到发现错误的行吗?
  • 实际上我的原始数据集有 3,095 行,但是当我运行上面的代码时,我得到了一个有 2,542 行的数据集。这是一个非常大的数字,因为最多应该有几百行。如果var2var1 中,我的目标是在给定年份获取这些行。请注意,每年都应该这样做。这意味着每年都是一个组。感谢您的帮助。
  • @Sharif,在这种情况下,你不需要在 var1 上使用 group_by,试试这个df %&gt;% mutate(xx = map2_lgl(var1, var2, ~ .x %in% var2 | .y %in% var1)) %&gt;% group_by(year) %&gt;% filter(any(xx))
  • 现在我在运行这个新代码后得到了所有 3,095 行。
【解决方案2】:

这听起来可能很冗长,但我认为它非常可靠:

library(dplyr)
library(purrr)

df %>%
  filter(year %in% 
           (combn(unique(df$year), 2) %>%
           t() %>% 
           as.data.frame() %>%
           mutate(common = pmap_lgl(., ~ length(intersect(df$var1[df$year == ..1], df$var2[df$year == ..2])) > 0)) %>%
           filter(common) %>%
           select(-common) %>%
           unlist() %>%
           unique()))

# A tibble: 6 x 3
   year  var1   var2
  <dbl> <dbl>  <dbl>
1  2005  2136 125860
2  2005  2136   1318
3  2005  2136 127464
4  2006  2285   8972
5  2006  2285   2136
6  2006  2285   5046

【讨论】:

  • 实际上它适用于这个示例问题,但对于大型数据集,它给出的答案与我想要的不匹配。任何的想法?我认为一开始将数据集按yearvar1 分组很重要,然后可以应用其他功能。
【解决方案3】:

dplyr 建议:

uniqyears <- unique(df1$year)
keepyears <- sapply(uniqyears,
                    function(yr) any(df1$var1[df1$year == yr] %in% df1$var2[df1$year != yr] |
                      df1$var2[df1$year == yr] %in% df1$var1[df1$year != yr]))
keepyears
# [1]  TRUE  TRUE FALSE
filter(df1, year %in% uniqyears[keepyears])
# # A tibble: 6 x 3
#    year  var1   var2
#   <dbl> <dbl>  <dbl>
# 1  2005  2136 125860
# 2  2005  2136   1318
# 3  2005  2136 127464
# 4  2006  2285   8972
# 5  2006  2285   2136
# 6  2006  2285   5046

【讨论】:

  • 实际上它适用于这个示例问题,但对于大型数据集,它给出的答案与我想要的不匹配。任何的想法?我认为一开始将数据集按yearvar1 分组很重要,然后可以应用其他功能。
  • 如果您可以更新样本数据以反映您在实际数据中看到的值的种类(即,我可能没有从您的规则中正确解释的一些异常),那么也许我(或某人else) 可以看看。
猜你喜欢
  • 1970-01-01
  • 2021-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-09
  • 2014-01-14
  • 2017-06-09
相关资源
最近更新 更多