比较不同数据帧中的不同列并创建新的循环R.

时间:2018-04-07 16:08:16

标签: r for-loop

我有两个看起来像这样的数据框

a
   Id   start stop
1  ABC  25    30
2  ACD  40    60
3  BCD  55    60

b
   Id   start stop
1  XYZ  20    50
2  ZXY  80    90
3  YZX  50    70

我想合并两个数据帧中的ID并将它们放入一个新的(如下所示),如果第一个数据帧中start列中的值较高而stop列中的值较低第一个数据框。因此,当[1,2]在a中高于[1,2]并且a中的[1,3]低于[1,3]时,两个数据帧中的id [1,1]变为进入新的数据框架。

1  ABC  XYZ
2  BCD  YZX

我正在尝试使用for循环执行此操作,如下所示,但似乎无法让它按我的意愿工作。任何帮助表示赞赏。我对R也很新,所以请保持简单:-)

a<-dataframe1
b<-dataframe2
for (i in 1:nrow(a)) {
  for (j in 1:nrow(b)) {
    if (a[i,2]>b[j,2] & a[i,3]<b[j,3]) {
      z<-as.data.frame(cbind(a[i,1],b[j,1]))
    }    
  }
}

2 个答案:

答案 0 :(得分:2)

使用data.table的解决方案可以实现为:

library(data.table)
setDT(a)
setDT(b)

a[b, .(Id_a = Id, Id_b = i.Id), on=.(start>=start , stop<=stop), nomatch = 0]
# Id_a Id_b
# 1:  ABC  XYZ
# 2:  BCD  YZX

选项#2:使用库sqldf

library(sqldf)
sqldf("SELECT a.ID as Id_a, b.ID as Id_b 
       FROM a, b
       WHERE a.start >= b.start AND a.stop <= b.stop")
#    Id_a Id_b
# 1  ABC  XYZ
# 2  BCD  YZX

数据

a <- read.table(text = 
"Id   start stop
ABC  25    30
ACD  40    60
BCD  55    60",
header = TRUE, stringsAsFactors = FALSE)

b <- read.table(text = 
"Id   start stop
XYZ  20    50
ZXY  80    90
YZX  50    70",
header = TRUE, stringsAsFactors = FALSE)

答案 1 :(得分:1)

以下是使用R / Bioconductor库findOverlaps中的GenomicRanges的一种可能性:

library(GenomicRanges);
gr.a <- makeGRangesFromDataFrame(cbind.data.frame(seqnames = 1, a), keep = T);
gr.b <- makeGRangesFromDataFrame(cbind.data.frame(seqnames = 1, b), keep = T);

hits <- findOverlaps(gr.a, gr.b, type = "within");
cbind.data.frame(
    from_a = mcols(gr.a[queryHits(hits)])$Id,
    from_b = mcols(gr.b[subjectHits(hits)])$Id)
#  from_a from_b
#1    ABC    XYZ
#2    BCD    YZX

注意:我在这里使用GenomicRanges因为它的间隔操作不同;似乎R库intervals提供了类似的功能。

样本数据

a <- read.table(text =
    "Id   start stop
1  ABC  25    30
2  ACD  40    60
3  BCD  55    60", header = T, row.names = 1)

b <- read.table(text =
   "Id   start stop
1  XYZ  20    50
2  ZXY  80    90
3  YZX  50    70", header = T, row.names = 1)