Сопоставить два столбца с двумя другими столбцами
У меня есть несколько строк данных (вкладка разделена). Я хочу найти строку, которая соответствует элементам из двух столбцов (3-й и 4-й) в каждой строке с двумя другими столбцами (10-й и 11-й). Например, в строке 1, 95428891 и 95443771 в столбце столбца 3 и 4 соответствуют элементам в столбцах столбцов 10 и 11 в строке строка 19. Точно так же верно и обратное. Элементы в столбцах столбцов 3 и 4 в 19-й строке также соответствуют элементам в столбцах столбцов 10 и 11 в строке 1. Мне нужно иметь возможность проходить каждую строку и выводить индексы строк для соответствующих совпадений. Возможно, иногда только один из столбцов совпадает вместо обоих (потому что иногда есть повторяющиеся числа), но мне нужно выбрать только строки, в которых совпадают оба столбца, а также там, где встречается взаимное совпадение. Поэтому было бы неплохо выводить индексы строк, где есть взаимное совпадение, например, 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
Вы не указали, что вы считаете правильным ответом, и ваша терминология кажется немного расплывчатой, когда вы говорите о "где встречается взаимное совпадение", но если я правильно понимаю задачу, как найти все строки, где 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 с логическими элементами и я я беру логическое "и" из двух таких матриц. Таким образом, строки, где есть совпадения с другими строками, следующие:
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
Таким образом, набор без совпадений, предполагая, что data.frame с именем indat, является:
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, ]
Ответ 2
Ответ DWin прочен, однако с массивными массивами, обычно более 50 тыс. или около того, вы столкнетесь с проблемами памяти, так как создаваемые матрицы огромны.
Я бы сделал что-то вроде:
match(
interaction( indat$V3, indat$V10),
interaction( indat$V4, indat$V11)
);
Которая объединяет все значения, представляющие интерес, в факторы и делает совпадение.
Это менее чистое решение, но более быстрое и управляемое.
Ответ 3
Ниже функция compare
использует возможности R для быстрой сортировки. Аргументы функции a
и b
являются матрицами; строки в a
- screend для сопоставления строк в b
для любого количества столбцов. В случае, если порядок столбцов не имеет значения, установите row_order=TRUE
для сортировки строк в порядке возрастания. Предположим, что функция должна работать также с колонками данных и столбцами символов/факторов, а также дублировать записи в a
и/или b
. Несмотря на использование for
и while
, он относительно быстро возвращает первое соответствие строки в b
для каждой строки a
(или 0
, если совпадение не найдено).
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,]