【问题标题】:How do I filter rows on a subset of columns?如何过滤列子集上的行?
【发布时间】:2018-11-15 17:36:06
【问题描述】:

df 的尾巴:

          fruit Letter Points     A    B     C       D
16       cherry      P   7876 11.43 7.23 13.72 4.29.01
17 chili pepper      Q   7831 10.85 7.18 14.14 4.33.90
18   clementine      R   7827 11.07 7.24 14.19 4.56.52
19   cloudberry      S   7704 10.38 7.73 14.32       X
20      coconut      T   7634 11.21 7.12 13.25 4.57.92
21    cranberry      U   7346 10.88 6.65 13.80 4.32.50

这似乎是一个常见问题,但我看到的所有答案都是基于对一列或所有列的过滤。在这里,我想删除 only A 到 D 列中包含“X”的行。

根据之前的答案,如果我只想过滤一列,我可以这样做:

df <- df[!grepl("X", df$D),]

这很好用,但我只能手动执行此操作,因为我知道 先验“X”在哪里。由于我想过滤许多相同格式的 df,我需要一种方法来过滤 A 到 D 列。

直觉上我想我可以扩展 grepl 中的参数以包含我想要过滤的列:

df <- df[!grepl("X", df[,c("A","B","C","D")]),]df1 <- df1[!grepl("X", df1[,4:7]),]

但是,这最终会删除不包含“X”的行,更不用说 A-D 列中的字母了。我猜这是因为 grep 系列函数不接受多个向量?

理想情况下,我想要一个基本解决方案,因为我被一些应该很容易理解的东西难住了。

完整的df:

df <- structure(list(fruit = c("apple", "apricot", "avocado", "bell pepper", 
"bilberry", "blackberry", "blood orange", "blueberry", "boysenberry", 
"canary melon", "cantaloupe", "cherimoya", "chili pepper", "clementine", 
"cloudberry", "cranberry"), Letter = c("A", "B", "C", "E", "F", 
"G", "I", "J", "K", "M", "N", "O", "Q", "R", "S", "U"), Points = c(8900, 
8757, 8742, 8554, 8531, 8461, 8206, 8153, 8113, 8106, 8050, 8017, 
7831, 7827, 7704, 7346), A = c("10.54", "10.64", "10.69", "10.64", 
"10.76", "10.99", "10.81", "11.00", "10.84", "11.05", "10.72", 
"10.84", "10.85", "11.07", "10.38", "10.88"), B = c("8.03", "7.88", 
"7.78", "7.24", "7.92", "7.59", "7.68", "7.32", "7.37", "7.34", 
"7.18", "6.89", "7.18", "7.24", "7.73", "6.65"), C = c("16.68", 
"15.19", "14.14", "15.72", "14.50", "14.75", "15.64", "14.19", 
"15.09", "15.10", "14.66", "14.20", "14.14", "14.19", "14.32", 
"13.80"), D = c("4.42.33", "4.35.06", "4.35.59", "4.23.13", "4.23.23", 
"4.29.93", "4.48.64", "4.21.06", "4.30.12", "4.52.35", "5.00.38", 
"4.48.11", "4.33.90", "4.56.52", "X", "4.32.50")), row.names = c(1L, 
2L, 3L, 5L, 6L, 7L, 9L, 10L, 11L, 13L, 14L, 15L, 17L, 18L, 19L, 
21L), class = "data.frame")

【问题讨论】:

  • df[!grepl('X',do.call(paste,df[4:7])),]

标签: r dplyr


【解决方案1】:

取决于您的数据结构:

df[!grepl('X',do.call(paste,df[4:7])),]

应该可以。

如果您有其他值,例如 23X.4,并且您想维护它们,那么您可以使用如下所示的正则表达式:

df[!grepl('(?m)^X$',do.call(paste,c(sep='\n',df[4:7])),perl = T),]

【讨论】:

    【解决方案2】:
    cols = c("A",  "B", "C", "D")
    df[! rowSums(df[cols] == "X"), ]
    

    这将从df 中删除行,其中任何cols 中的值 "X"(不包含"X",因为其他一些答案是做)。

    【讨论】:

      【解决方案3】:

      我们可以遍历感兴趣的列,检查值是否等于"X"(根据数据,它是完全匹配的),然后Reduce list 的逻辑vectors 到单个 vector| 并使用它来子集数据

      df[!Reduce(`|`, lapply(df[c("A", "B", "C", "D")], `==`, "X")),]
      

      grepl(如果不准确)

      df[!Reduce(`|`, lapply(df[c("A", "B", "C", "D")], grepl, pattern = "X")),]
      

      或使用tidyverse

      library(tidyverse)
      df %>% 
         filter_at(vars(A:D), any_vars(!grepl('X', .)))
      

      【讨论】:

        【解决方案4】:

        使用 dplyr 删除任何列 A、B、C 或 D 中的值等于“X”的任何行如下所示:

        library(dplyr)
        filter_at(df, vars(A:D), any_vars(!. == 'X'))
        

        【讨论】:

        • 看起来您正在匹配字符串中出现的“X”,而不是直接匹配“X”。
        猜你喜欢
        • 2021-09-05
        • 2015-04-04
        • 1970-01-01
        • 2017-07-28
        • 1970-01-01
        • 1970-01-01
        • 2021-10-05
        • 1970-01-01
        相关资源
        最近更新 更多