【问题标题】:Filtering rows in dataframe based on partial column name and mathematical expression根据部分列名和数学表达式过滤数据框中的行
【发布时间】:2017-06-28 19:34:16
【问题描述】:

我正在尝试找到一种方法来使用列标题的部分名称和数学表达式 (x > 0) 来过滤行。鉴于我在这里的数据:

    OTU_ID       X3_22L15_S   X3_22T10_W   X3_22L6_S   X3_22Algae 
1   denovo109       16            0            9            0
2   denovo147       44          484           28            0
3   denovo297        0            0            7           14
4   denovo1013       0            1            0            0

我只想在标题以“S”结尾的列和以“W”结尾的列中包含值 > 0 的行。我找到了基于列标题的子字符串过滤列的方法以及基于某个列中的值进行过滤的方法,但没有找到任何允许我根据在两组中同时出现的 > 0 的值进行过滤的方法由不同子字符串指定的列。

任何帮助将不胜感激!

【问题讨论】:

  • 无论行中的值是什么,是否都希望列以“W”结尾?
  • 是的。我只需要在任何以 W 结尾的列和任何以 S 结尾的列中值 > 0 的行。
  • 我明白了。我通过将all_vars 替换为any_vars 来更新我的答案。如果这是您想要的,请告诉我。
  • 看到 Jaap 的回答后,我认为分隔 filter_at 调用可能是过滤数据的最佳方式。我进一步更新了我的答案。

标签: r


【解决方案1】:

我们可以使用dplyr 包中的filter_atdt2 是最终输出。

# Load package
library(dplyr)

# Create example data frame
dt <- read.table(text = "    OTU_ID       X3_22L15_S   X3_22T10_W   X3_22L6_S   X3_22Algae 
1   denovo109       16            0            9            0
                 2   denovo147       44          484           28            0
                 3   denovo297        0            0            7           14
                 4   denovo1013       0            1            0            0",
                 header = TRUE, stringsAsFactors = FALSE)

# Filter the data, with any column ends with "S" or "W" and values > 0
dt2 <- dt %>%
  filter_at(vars(ends_with("S")), any_vars(. > 0)) %>%
  filter_at(vars(ends_with("W")), any_vars(. > 0))

【讨论】:

    【解决方案2】:

    使用:

    cols <- grep('[SW]$', names(df), value = TRUE)
    df[rowSums(df[, cols] > 0) == length(cols),]
    

    给予:

         OTU_ID X3_22L15_S X3_22T10_W X3_22L6_S X3_22Algae
    2 denovo147         44        484        28          0
    

    这假设您只想为以SW 结尾的列保留所有值都大于零的行。

    注意:value = TRUE 可以在 grep 中省略,然后返回一个数字向量


    在回复您的评论时,如果要将以 W 结尾的列与以 S 结尾的列分开处理,您可以这样做:

    wcols <- grep('W$', names(df), value = TRUE)
    scols <- grep('S$', names(df), value = TRUE)
    
    df[rowSums(df[, wcols, drop = FALSE] > 0) & rowSums(df[, scols, drop = FALSE] > 0),]
    

    给出:

         OTU_ID X3_22L15_S X3_22T10_W X3_22L6_S X3_22Algae
    2 denovo147         44        484        28          0
    

    【讨论】:

    • 谢谢!这确实适用于所有以 W 结尾的列和所有以 S 结尾的列的值 > 0 的行,但我意识到我应该更具体。有没有办法在任何以 W 结尾的列和任何以 S 结尾的列中保留值 > 0 的行?
    【解决方案3】:

    可以使用函数grep。这是一种方法:

    library(dplyr)
    
    # Create example data frame
    dt <- read.table(text = "    OTU_ID       X3_22L15_S   X3_22T10_W   X3_22L6_S   X3_22Algae 
    1   denovo109       16            0            9            0
                     2   denovo147       44          484           28            0
                     3   denovo297        0            0            7           14
                     4   denovo1013       0            1            0            0",
                     header = TRUE, stringsAsFactors = FALSE)
    
    # Filter the data, with any column ends with "S" or "W" and values > 0
    df2 <- dt[,grep(pattern="^Algae",colnames(dt)]
    
    
    dt2 <- dt %>%
      filter_at(vars(ends_with("W")), any_vars(. > 0))
    
    
    df2 <- data.frame(dt[,grep(pattern="Algae",colnames(dt))])
    
    
    dt <- dt %>%
      filter_at(vars(ends_with("S")), any_vars(. > 0)) %>%
      filter_at(vars(ends_with("W")), any_vars(. > 0))  
    
    dt2 <- data.frame(dt[,-grep(pattern="Algae",colnames(dt))])
    

    在执行dt2 时,会得到以下输出:

    > dt2
         OTU_ID X3_22L15_S X3_22T10_W X3_22L6_S
    1 denovo147         44        484        28
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多