【问题标题】:Filter Data Frame by Matching Multiple String in Multiple Columns通过匹配多列中的多个字符串来过滤数据框
【发布时间】:2017-07-10 01:28:44
【问题描述】:

我一直没有成功尝试使用dplyrgrep 库过滤我的数据框,并使用我的数据框多列中的字符串列表。我认为这是一项简单的任务,但要么没有人问过我的具体问题,要么不像我最初想象的那么容易。

对于下面的数据框...

foo <- data.frame(var.1 = c('a', 'b',' c'),
           var.2 = c('b', 'd', 'e'),
           var.3 = c('c', 'f', 'g'),
           var.4 = c('z', 'a', 'b'))

... 我希望能够逐行过滤以查找包含所有三个变量 a、b 和 c 的行。 我寻求的答案只会返回第 1 行,因为它包含 a、b 和 c,而不返回第 2 行和第 3 行,即使它们包含三个寻求变量中的两个,它们也不包含所有三个变量同一行。

我遇到了grep 只允许一次指定向量或一列的问题,而我真的只关心在同一行的许多列中查找字符串。

我还使用dplyrfilter 使用%in%,但它只会在任何变量存在时返回:

foo %>% 
  filter(var.1 %in% c('a', 'b', 'c') |
           var.2 %in% c('a', 'b', 'c') |
           var.3 %in% c('a', 'b', 'c'))

感谢您的任何帮助,如果您需要任何说明,请告诉我!

【问题讨论】:

  • foo[apply(foo, 1, function(x) all(c('a', 'b', 'c') %in% x)), ]
  • apply( foo, 2, function(x) all( grepl(x = x, pattern = "[abc]" ) ))
  • apply( foo, 2, function(x) sum( grepl(x = x, pattern = "[abc]" ) ) == 3)

标签: r dplyr subset


【解决方案1】:

这是基于 R 的一种方法,我们检查 foo 的元素是否连续等于 "a""b""c",添加布尔值并检查每行的这些布尔值的总和大于等于3

Reduce("+", lapply(c("a", "b", "c"), function(x) rowSums(foo == x) > 0)) >=3
#[1]  TRUE FALSE FALSE

时间

foo = matrix(sample(letters[1:26], 1e7, replace = TRUE), ncol = 5)
system.time(Reduce("+", lapply(letters[1:20], function(x) rowSums(foo == x) > 0)) >=20)
#   user  system elapsed 
#   3.26    0.48    3.79 

system.time(apply(foo, 1, function(x) all(letters[1:20] %in% x)))
#   user  system elapsed 
#  18.86    0.00   19.19 


identical(Reduce("+", lapply(letters[1:20], function(x) rowSums(foo == x) > 0)) >=20, 
          apply(foo, 1, function(x) all(letters[1:20] %in% x)))
#[1] TRUE
> 

【讨论】:

    【解决方案2】:

    您的问题源于尝试将“tidyverse”解决方案应用于不整洁的数据。这是整洁的解决方案,它使用melt 使您的数据整洁。看看这个解决方案有多整洁?

    > library(reshape2)
    > rows = foo %>%
          mutate(id=1:nrow(foo)) %>% 
          melt(id="id") %>% 
          filter(value=="a" | value=="b" | value=="c") %>%
          group_by(id) %>% 
          summarize(N=n()) %>% 
          filter(N==3) %>%
          select(id) %>%
          unlist
    Warning message:
    attributes are not identical across measure variables; they will be dropped 
    

    这为您提供了匹配行索引的向量,然后您可以使用以下方法对原始数据框进行子集化:

    > foo[rows,]
      var.1 var.2 var.3 var.4
    1     a     b     c     z
    > 
    

    【讨论】:

    • value=="a" | value=="b" | value=="c" 肯定是value %in% c("a","b","c")
    猜你喜欢
    • 2022-01-10
    • 1970-01-01
    • 2023-03-19
    • 2020-02-10
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多