【问题标题】:Filter if function returns FALSE过滤函数是否返回 FALSE
【发布时间】:2018-11-15 14:48:48
【问题描述】:

我有一个数据框,其中包含一个以逗号分隔的单词列表的列:

   df <- data.frame(gene=c("1", "2", "3", "4"), affected_genes = c("Rim2, CG18208", "ANB, XYZ", "Gene1, Gene2", "XYZ"))

 gene affected_genes
    1  Rim2, CG18208
    2       ANB, XYZ
    3   Gene1, Gene2
    4            XYZ

我想过滤掉affected_genes 不包含XYZ 的行。这是我正在尝试的:

library(dplyr)

geneIn <- function(gene, gene_list){
    gene %in% sapply(gene_list, function(x) strsplit(x, ", ")[[1]], USE.NAMES=FALSE)
  }


df %>%
    dplyr::filter(geneIn("XYZ", affected_genes))

但是,Error in filter_impl(.data, quo) : Evaluation error: non-character argument. 失败

当我跑步时:

affected_genes <- "ANB, XYZ"
geneIn("XYZ", affected_genes)

我得到了我的预期结果 (TRUE)。谁能建议我在第一个示例中做错了什么?

【问题讨论】:

  • 我建议你创建一些整洁的数据。即使是列表列也会比您现在拥有的更好。
  • 您的geneIn 函数应该将affected_gene 的向量作为输入并返回一个布尔向量。
  • 你的affected_genes列有没有可能是一个因素而不是字符?如果您使用您的数据但添加 stringsAsFactors=FALSE 它工作正常。好吧,不好,但它不会给出这个错误。
  • 仅供参考,您可以简单地做df[grepl('\\bXYZ\\b', df$affected_genes),]

标签: r dplyr


【解决方案1】:

两件事:您的 df$affected_genes 似乎是一个因素,因此要么将它们放入 char 类(例如,通过在您的 read.table 调用中包含 stringsAsFactors=FALSE),要么首先通过 as.character 传递列。其次,您要将您的%in% 插入sapply,否则您将得到一个长度为 1 的向量作为响应(它将检查该基因是否出现在所有单个基因名称列表中的任何位置) , 而不是每行的 TRUE/FALSE。总体而言,您的函数代码应为:

geneIn <- function(gene, gene_list) {
            sapply(as.character(gene_list), function(x) gene %in% strsplit(x, ", ")[[1]], USE.NAMES=FALSE)
          }

效果很好:

df %>% dplyr::filter(geneIn("XYZ", affected_genes))

  gene affected_genes
1    2       ANB, XYZ
2    4            XYZ

【讨论】:

    【解决方案2】:

    你不应该在一个字符串中有多个基因。 Hadley Wickham 定义的“整洁数据”概念需要这种格式:

    gene affected_gene
       1          Rim2
       1       CG18208
       2           ANB
       2           XYZ
          ...
    

    但是,如果您想进一步分析这些数据,您至少应该拆分字符串并创建一个列表列:

    df$affected_genes <-  lapply(strsplit(as.character(df$affected_genes), ","), trimws)
    df[vapply(df$affected_genes, `%in%`, x = "XYZ", FUN.VALUE = logical(1)),]
    #  gene affected_genes
    #2    2       ANB, XYZ
    #4    4            XYZ
    

    使用上面整洁的格式,您将不需要 *apply 循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 2020-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-19
      相关资源
      最近更新 更多