提问人:Rhea Bedi 提问时间:7/1/2023 更新时间:7/2/2023 访问量:47
如何从两个 DataFrame 中提取基于两个条件匹配的行
how to extract rows which match based on two conditions from two dataframes
问:
我有两个数据帧,一个是 snp 区域,另一个是 Hic 区域。
dput(hic_region[1:15,1:4])
structure(list(rf1 = c(57584944, 57584944, 57584944, 57584944,
57584944, 57584944, 57584944, 57584944, 50263463, 5e+07, 50263463,
50263463, 35172197, 35172197, 57584944), rt1 = c(57624944, 57624944,
57624944, 57624944, 57624944, 57624944, 57624944, 57624944, 50303463,
51423463, 50303463, 50303463, 35212197, 35212197, 57624944),
rf2 = c(1899354, 1899354, 1899354, 1899354, 1899354, 1579354,
1899354, 1899354, 1899354, 1779354, 1899354, 1899354, 1899354,
1899354, 1499354), rt2 = c(1939354, 1939354, 1939354, 1939354,
1939354, 1619354, 1939354, 1939354, 1939354, 1819354, 1939354,
1939354, 1939354, 1939354, 1539354)), row.names = c(NA, -15L
), class = c("tbl_df", "tbl", "data.frame"))
> dput(snp_region[1:10,1:6])
structure(list(Gene = c("ENSG00000132819", "ENSG00000101162",
"ENSG00000132819", "ENSG00000101162", "ENSG00000101162", "ENSG00000101162",
"ENSG00000101162", "ENSG00000101162", "ENSG00000101162", "ENSG00000101162"
), `Gene-Chr` = c(20, 20, 20, 20, 20, 20, 20, 20, 20, 20), `Gene-Pos` = c(55975426,
57598009, 55975426, 57598009, 57598009, 57598009, 57598009, 57598009,
57598009, 57598009), RsId = c("rs6084653", "rs156356", "rs1741314",
"rs6136489", "rs4814776", "rs13042885", "rs4814779", "rs6045615",
"rs11696739", "rs4618126"), `SNP-Chr` = c(20, 20, 20, 20, 20,
20, 20, 20, 20, 20), `SNP-Pos` = c(4157072, 1819280, 4155193,
1923734, 1921523, 1924707, 1923271, 1931582, 1600925, 1930885
)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
))
我想将 snp 区域中存在的基因与从 rf1 到 rt1 的 hic 区域相匹配,如果它存在于这两个区域(rf1 和 rt1)之间,请选择该基因,然后使用 rf2 和 rt2 区域匹配 snp 区域的 snp 位置。 我写了一个代码,但它给了我重复的值。
snp <- data.frame()
for(i in 1:dim(snp_region)[1]){
snp_pos <- snp_region$`SNP-Pos`[i]
for(j in 1:dim(hic_region)[1]){
if(snp_region$`Gene-Pos`[i] %in% seq(hic_region$rf1[j],hic_region$rt1[j],1)){
hic_region1 <- hic_region[j,]
if(snp_pos %in% seq(hic_region1$rf2,hic_region1$rt2,1)){
preset <<- snp_region[i,]
}
}
}
snp <- rbind(snp,preset)
}
dput(snp[1:5,1:6])
structure(list(Gene = c("ENSG00000131069", "ENSG00000131069",
"ENSG00000131069", "ENSG00000101162", "ENSG00000101162"), `Gene-Chr` = c(20,
20, 20, 20, 20), `Gene-Pos` = c(33487859, 33487859, 33487859,
57598009, 57598009), RsId = c("rs4142441", "rs4142441", "rs4142441",
"rs6136489", "rs4814776"), `SNP-Chr` = c(20, 20, 20, 20, 20),
`SNP-Pos` = c(42839620, 42839620, 42839620, 1923734, 1921523
)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"
))
如果我做错了什么,或者是否有更好的方法来运行两个条件来匹配两个数据帧的行,我想得到一些反馈。 谢谢。
答:
2赞
jkatam
7/1/2023
#1
请尝试以下代码,您将获得与snp_region
在这里你会得到 2flg
flg
表示从 RF1 到 RT1 的 SNP 区域到 HIC 区域,如果它存在于这两个区域(RF1 和 RT1)之间
flg2
表示使用 RF2 和 RT2 区域的 SNP 区域的 SNP 位置匹配。
library(tidyverse)
snp_region2 <- snp_region %>% mutate(row=row_number())
snp_region2 %>% cross_join(hic_region) %>%
mutate(flg=ifelse(between(`Gene-Pos`,rf1,rt1),1,NA),
flg2=ifelse(flg==1 & between(`SNP-Pos`,rf2,rt2),1,NA)) %>%
group_by(row) %>% slice_head(n=1) %>% filter(!is.na(flg)|!is.na(flg2))
# output
# A tibble: 8 × 13
# Groups: row [8]
Gene `Gene-Chr` `Gene-Pos` RsId `SNP-Chr` `SNP-Pos` row rf1 rt1 rf2
<chr> <dbl> <dbl> <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 ENSG0000… 20 57598009 rs15… 20 1819280 2 5.76e7 5.76e7 1.90e6
2 ENSG0000… 20 57598009 rs61… 20 1923734 4 5.76e7 5.76e7 1.90e6
3 ENSG0000… 20 57598009 rs48… 20 1921523 5 5.76e7 5.76e7 1.90e6
4 ENSG0000… 20 57598009 rs13… 20 1924707 6 5.76e7 5.76e7 1.90e6
5 ENSG0000… 20 57598009 rs48… 20 1923271 7 5.76e7 5.76e7 1.90e6
6 ENSG0000… 20 57598009 rs60… 20 1931582 8 5.76e7 5.76e7 1.90e6
7 ENSG0000… 20 57598009 rs11… 20 1600925 9 5.76e7 5.76e7 1.90e6
8 ENSG0000… 20 57598009 rs46… 20 1930885 10 5.76e7 5.76e7 1.90e6
# ℹ 3 more variables: rt2 <dbl>, flg <dbl>, flg2 <dbl>
评论
0赞
Till
7/1/2023
我喜欢这个解决方案!不错的应用程序。我认为您可以省略并简单地使用条件创建一个 ,这通常对下游任务更有用。喜欢:dplyr::between()
ifelse()
logical
flg=between(`Gene-Pos`, rf1, rt1)
0赞
jkatam
7/1/2023
我是一名SAS程序员,所以习惯于创建这样的标志变量。但我同意你的评论。谢谢
0赞
jkatam
7/2/2023
您选择的答案返回 7 行,我的答案返回 8 行,我很想知道哪个是正确的
0赞
Jamie
7/2/2023
@jkatam - 我相信 OP 希望包含该基因,如果并且在 rf/rt 变量的范围内。例如,对于同一行。在您的输出中,仅满足一半标准的基因。 匹配但不匹配。Gene-Pos
SNP-Pos
RsId == rs156356
Gene-Pos
SNP-Pos
1赞
Jamie
7/1/2023
#2
这是使用 .此过程称为联接。data.table
non-equi
在该部分中,您可以创建介于 和 AND 之间的逻辑。然后选择要包含在两个表中的列。on
Gene-Pos
rt1
rf2
SNP-Pos
rf2
rt2
library(data.table)
setDT(hic_region)
setDT(snp_region)
matched_genes = unique(snp_region[
hic_region,
on = .(`Gene-Pos` >= rf1, `Gene-Pos` <= rt1, `SNP-Pos` >= rf2, `SNP-Pos` <= rt2),
.(Gene, `Gene-Chr`, `Gene-Pos`=`x.Gene-Pos`, RsId, `SNP-Chr`, `SNP-Pos`=`x.SNP-Pos`, rf1, rt1, rf2, rt2),
nomatch = NULL
])
matched_genes
# Output
Gene Gene-Chr Gene-Pos RsId SNP-Chr SNP-Pos rf1 rt1 rf2 rt2
1: ENSG00000101162 20 57598009 rs6136489 20 1923734 57584944 57624944 1899354 1939354
2: ENSG00000101162 20 57598009 rs4814776 20 1921523 57584944 57624944 1899354 1939354
3: ENSG00000101162 20 57598009 rs13042885 20 1924707 57584944 57624944 1899354 1939354
4: ENSG00000101162 20 57598009 rs4814779 20 1923271 57584944 57624944 1899354 1939354
5: ENSG00000101162 20 57598009 rs6045615 20 1931582 57584944 57624944 1899354 1939354
6: ENSG00000101162 20 57598009 rs4618126 20 1930885 57584944 57624944 1899354 1939354
7: ENSG00000101162 20 57598009 rs11696739 20 1600925 57584944 57624944 1579354 1619354
评论