如果函数返回FALSE

时间:2018-11-15 14:48:49

标签: r dplyr

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

   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)。在我的第一个示例中,谁能建议我做错了什么?

2 个答案:

答案 0 :(得分:4)

两件事:您的df$affected_genes似乎是一个因素,因此要么使它们成为char类(例如,通过在您的stringsAsFactors=FALSE调用中包含read.table),要么将该列传递给首先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

答案 1 :(得分: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循环。