сопоставить два столбца с двумя другими столбцами - PullRequest
10 голосов
/ 30 июля 2011

У меня есть несколько строк данных (разделенных табуляцией). Я хочу найти строку, которая соответствует элементам из двух столбцов (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

Ответы [ 3 ]

20 голосов
/ 12 сентября 2012

Ответ DWin твердый, однако с массивами большого размера, обычно более 50 КБ, вы столкнетесь с проблемами памяти, поскольку создаваемые вами матрицы огромны.

Я бы сделал что-то вроде:

match(
  interaction( indat$V3, indat$V10),
  interaction( indat$V4, indat$V11)
);

, который объединяет все значения, представляющие интерес, в факторы и сопоставляет их.

Это менее чистое решение, но более быстрое и более управляемое.

9 голосов
/ 30 июля 2011

Вы не указали, что вы считаете правильным ответом, и ваша терминология кажется немного расплывчатой, когда вы говорите «где есть взаимное совпадение», но если я правильно понимаю задачу как поиск всех строк, где 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

Итак, набор с no совпадает, предполагая, что 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, ]
0 голосов
/ 05 сентября 2016

Приведенная ниже функция compare использует возможности R для быстрой сортировки.Аргументы функции a и b являются матрицами;строки в a являются скринами для сопоставления строк в 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,]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...