r-如何通过字符串列半连接两个数据帧,其中一个数据帧用冒号分隔



我有两个数据帧,dfadfb:

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()

这里有一个使用stringrpurrr的解决方案。

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"))

不过有一个缺点:速度很慢。。。

相关内容

  • 没有找到相关文章

最新更新