我有两个数据帧,dfa
和dfb
:
dfa <- data.frame(
gene_name = c("MUC16", "MUC2", "MET", "FAT1", "TERT"),
id = c(1:5)
)
dfb <- data.frame(
gene_name = c("MUC1", "MET; BLEP", "MUC21", "FAT", "TERT"),
id = c(6:10)
)
看起来像这样:
> dfa
gene_name id
1 MUC16 1
2 MUC2 2
3 MET 3
4 FAT1 4
5 TERT 5
> dfb
gene_name id
1 MUC1 6
2 MET; BLEP 7
3 MUC21 8
4 FAT 9
5 TERT 10
dfa
是我感兴趣的基因列表:我想把dfb
行放在它们出现的地方,注意数字(MUC1
是而不是MUC16
(。我的new_df
应该是这样的:
> new_df
gene_name id
1 MET; BLEP 7
2 TERT 10
我的问题是,常规的dplyr::semi_join()
确实匹配,这没有考虑到dfb$gene_names
可以包含与"; "
分离的基因这一事实。这意味着在该示例中,"MET"
不被保留。
我试着研究fuzzyjoin::regex_semi_join
,但我不能让它做我想做的事。。。
一个小规模的解决方案是受欢迎的。(可能使用stringr
?!(
编辑:后续问题。。。
我该如何做倒数anti_join
?在这种方法中简单地将semi_join
更改为anti_join
是不起作用的,因为行MET; BLEP
在不应该出现的时候…
在anti_join
之后添加filter(gene_name == new_col)
可以使用所提供的简单数据集,但如果我像这样扭曲它:
dfa <- data.frame(
gene_name = c("MUC16", "MUC2", "MET", "FAT1", "TERT"),
id = c(1:5)
)
dfb <- data.frame(
gene_name = c("MUC1", "MET; BLEP", "MUC21; BLOUB", "FAT", "TERT"),
id = c(6:10)
)
然后就没有了。在我的真实数据集中,dfa
不包含分号,它只是单个基因名称的一列。但是dfb
包含了大量的信息,并且分号的多种组合。。。
您可以在加入之前使用seperate_rows()
来拆分数据帧。注意,如果BLEP
存在于dfa中,它将导致重复,这就是为什么使用distinct 的原因
dfa <- data.frame(
gene_name = c("MUC16", "MUC2", "MET", "FAT1", "TERT"),
id = c(1:5),
stringsAsFactors = FALSE
)
dfb <- data.frame(
gene_name = c("MUC1", "MET; BLEP", "MUC21", "FAT", "TERT"),
id = c(6:10),
stringsAsFactors = FALSE
)
library(tidyverse)
dfb%>%
mutate(new_col = gene_name)%>%
separate_rows(new_col,sep = "; ")%>%
semi_join(dfa,by = c("new_col" = "gene_name"))%>%
select(gene_name,id)%>%
distinct()
这里有一个使用stringr
和purrr
的解决方案。
library(tidyverse)
dfb %>%
mutate(gene_name_list = str_split(gene_name, "; ")) %>%
mutate(gene_of_interest = map_lgl(gene_name_list, some, ~ . %in% dfa$gene_name)) %>%
filter(gene_of_interest == TRUE) %>%
select(gene_name, id)
我想我终于让fuzzyjoin::regex_joins
做了我想做的事。它非常简单,我只需要调整我的dfa
过滤器列表:
library(fuzzyjoin)
# add "b" regex expression before/after each gene of the list to filtrate from
# (to search for whole words)
dfa$gene_name <- paste0("\b", dfa$gene_name, "\b")
# to keep genes from dfb that are present in the dfa filter list
dfb %>%
regex_semi_join(dfa, by = c(gene_name = "gene_name"))
# to exclude genes from dfb that are present in the dfa filter blacklist
dfb %>%
regex_anti_join(dfa, by = c(gene_name = "gene_name"))
不过有一个缺点:速度很慢。。。