我有一个数据框,其中包含一列,该列包含用逗号分隔的单词列表:
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
)。在我的第一个示例中,谁能建议我做错了什么?
答案 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
循环。