将两列与另外两列匹配
Posted
技术标签:
【中文标题】将两列与另外两列匹配【英文标题】:match two columns with two other columns 【发布时间】:2011-10-16 08:45:03 【问题描述】:我有几行数据(制表符分隔)。我想找到与每行中两列 (3rd & 4th) 中的元素与另外两列 (10th & 11th) 匹配的行。例如,在第 1 行,第 3 和 4 列 中的 95428891 和 95443771 匹配 第 19 行中的第 10 和 11 列 中的元素/强>。同样,倒数也成立。 第 19 行的第 3 列和第 4 列中的元素也匹配 第 1 行中的第 10 列和第 11 列中的元素。我需要能够遍历每一行并输出相应匹配的行索引。有时可能只有一列匹配而不是两者匹配(因为有时有重复的数字),但我只需要选择两列都匹配以及相互匹配的行。因此,最好在存在相互匹配的情况下输出行索引,例如,1 & 19 作为制表符分隔值(可能在不同的 data.frame 对象中)。并且没有相互匹配的行可以单独输出。我正在尝试在 R 中实现这一点以遍历多行数据。
1313 chr2 95428891 95443771 14880 chr2:96036782 205673 + chr2 96036782 96052481
1313 chr2 95428896 95443771 14875 chr2:97111880 205214 - chr2 97111880 97127588
1313 chr2 95443771 95526464 82693 chr2:95609272 1748861 - chr2 95609272 95691902
1313 chr2 95477143 95486318 9175 chr2:97616847 177391 + chr2 97616847 97626039
1313 chr2 95486323 95521267 34944 chr2:97035158 268351 + chr2 97035158 97070183
1313 chr2 95515418 95525958 10540 chr2:95563236 132439 + chr2 95563236 95572666
1314 chr2 95563236 95572666 9430 chr2:95515418 132439 + chr2 95515418 95525958
1314 chr2 95563236 95572666 9430 chr2:95609778 126017 - chr2 95609778 95620287
1314 chr2 95563236 95569115 5879 chr2:97064308 89848 + chr2 97064308 97070183
164 chr2 95609272 95691902 82630 chr2:95443771 1748861 - chr2 95443771 95526464
1314 chr2 95609778 95620287 10509 chr2:95563236 126017 - chr2 95563236 95572666
1314 chr2 95614473 95649363 34890 chr2:97035158 394821 - chr2 97035158 97070173
1314 chr2 95649368 95658543 9175 chr2:97616847 177822 - chr2 97616847 97626039
164 chr2 95775062 95814080 39018 chr2:97578938 0 - chr2 97578938 97616780
1315 chr2 95778788 95781856 3068 chr2:97609982 31302 - chr2 97609982 97616788
164 chr2 95780657 95829665 49008 chr2:96053880 882178 - chr2 96053880 96102738
1316 chr2 95829982 95865446 35464 chr2:97296848 242680 - chr2 97296848 97333087
1316 chr2 95829982 95935104 105122 chr2:97438085 1169669 + chr2 97438085 97544431
1317 chr2 96036782 96052481 15699 chr2:95428891 205673 + chr2 95428891 95443771
【问题讨论】:
【参考方案1】:接受的答案有效,但是对于大型数组,通常超过 50k 左右,您会遇到内存问题,因为您正在创建的矩阵很大。
我会这样做:
match(
interaction( indat$V3, indat$V10),
interaction( indat$V4, indat$V11)
);
它将所有感兴趣的值连接成因子并进行匹配。
不确定这是否更快,但内存效率更高。
【讨论】:
【参考方案2】:您没有表明您认为正确答案是什么,并且当您谈论“存在互惠匹配”时,您的术语似乎有点含糊,但如果我正确理解该任务,即找到 col.3 = 的所有行= col.10 & col.4 == col.11,那么这应该完成任务:
which( outer(indat$V4, indat$V11, "==") &
outer(indat$V3, indat$V10, "=="),
arr.ind=TRUE)
# result
row col
[1,] 19 1
[2,] 10 3
[3,] 7 6
[4,] 8 6
[5,] 6 7
[6,] 11 8
[7,] 3 10
[8,] 7 11
[9,] 8 11
[10,] 1 19
外部函数将函数'FUN',在这种情况下为“==”,应用于x和y的所有双向组合,它的第一个和第二个参数,所以这里我们得到一个带有逻辑条目的nxn矩阵和I我正在采用两个这样的矩阵的逻辑“和”。所以与其他行匹配的行是:
unique( c(which( outer(indat$V4, indat$V11, "==") &
outer(indat$V3, indat$V10, "=="),
arr.ind=TRUE) ))
#[1] 19 10 7 8 6 11 3 1
所以与 no 匹配的集合,假设一个名为 indat 的 data.frame 是:
matches <- unique( c(which( outer(indat$V4, indat$V11, "==") &
outer(indat$V3, indat$V10, "=="), arr.ind=TRUE) ))
indat[ ! 1:NROW(indat) %in% matches, ]
匹配的有:
indat[ 1:NROW(indat) %in% matches, ]
【讨论】:
感谢您的回答。我所说的互惠匹配是什么意思,...查看第 1 行和第 19 行。第 1 行中第 3,4 列中的值与第 19 行中第 10,11 列中的值相同。同样,第 19 行中第 3,4 列中的值与第 1 行中的第 10,11 列相同。因此输出第 1 行和第 19 行。类似地,第 6 行和第 7 行在第 3,4 列和第 10,11 列中具有相互匹配。 @user645600 我的解决方案肯定已经确定了这些情况。我的复选标记在哪里? @什么是复选标记?我很少使用这个论坛并且不确定协议。 能不能也给arr.ind=TRUE
加个解释,它是干什么用的?谢谢。【参考方案3】:
下面的函数compare
利用了R的快速排序能力。函数参数a
和b
是矩阵; a
中的行被筛选以匹配b
中任意数量的列的行。如果列顺序无关紧要,请设置row_order=TRUE
以使行条目按升序排序。猜猜这个函数应该也适用于数据框和字符/因子列,以及a
和/或b
中的重复条目。尽管使用了for
和while
,但对于a
的每一行(或0
,如果未找到匹配项)返回b
中的第一行匹配相对较快。
compare<-function(a,b,row_order=TRUE)
len1<-dim(a)[1]
len2<-dim(b)[1]
if(row_order)
a<-t(apply(t(a), 2, sort))
b<-t(apply(t(b), 2, sort))
ord1<-do.call(order, as.data.frame(a))
ord2<-do.call(order, as.data.frame(b))
a<-a[ord1,]
b<-b[ord2,]
found<-rep(0,len1)
dims<-dim(a)[2]
do_dims<-c(1:dim(a)[2])
at<-1
for(i in 1:len1)
for(m in do_dims)
while(b[at,m]<a[i,m])
at<-(at+1)
if(at>len2)break
if(at>len2)break
if(b[at,m]>a[i,m])break
if(m==dims)found[i]<-at
if(at>len2)break
return(found[order(ord1)]) # indicates the first match of a found in b and zero otherwise
# example data sets:
a <- matrix(sample.int(1E4,size = 1E4, replace = T), ncol = 4)
b <- matrix(sample.int(1E4,size = 1E4, replace = T), ncol = 4)
b <- rbind(a,b) # example of b containing a
# run the function
found<-compare(a,b,row_order=TRUE)
# check
all(found>0)
# rows in a not contained in b (none in this example):
a[found==0,]
【讨论】:
以上是关于将两列与另外两列匹配的主要内容,如果未能解决你的问题,请参考以下文章
如何将两列与数据合并,如果一列的单元格为空,则相邻的单元格已满?