2016-12-01 6 views
0

У меня есть две таблицы в R (женщины и мужчины) с данными отсутствия присутствия. Я хотел бы сделать парные сравнения между ними (строка за строкой), чтобы найти количество ячеек, не разделяемых между каждой парой (т. Е. Сумма ячеек, равная 1 на самке, но не на самке и наоборот) ,Напротив кросс-продукта: как создать новую матрицу из пересечения двух матриц?

Я знаю, что крест продукта (% *%) делает противоположное тому, что мне нужно. Он создает новую матрицу, содержащую сумму разделяемых ячеек между парами самцов и самков (т. Е. Суммарными клетками, равными 1 в обоих).

Ниже приведен пример набора данных:

females <- as.data.frame(matrix(c(0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1), nrow=5, byrow=T)) 
males <- as.data.frame(matrix(c(1,0,0,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1,0,1), nrow=5, byrow=T)) 
rownames(females) <-c ("female_1","female_2","female_3","female_4","female_5") 
rownames(males) <-c ("male_1","male_2","male_3","male_4","male_5") 

Так что, если я декартово произведение

as.matrix(females) %*% t(as.matrix(males)) 

Я получаю

  male_1 male_2 male_3 male_4 male_5 
female_1  2  2  1  2  1 
female_2  1  2  0  2  0 
female_3  2  1  3  2  3 
female_4  3  3  2  4  2 
female_5  3  2  3  3  3 

Но мне нужно это (только первая строка)

  male_1 male_2 male_3 male_4 male_5 
female_1  1  1  3  2  3 
. 
. 

В действительности, мой набор данных не симметричен (у меня 47 женщин и 32 мужчины).

Спасибо за любую помощь !!!

+0

Вы можете видеть из кадра данных, что female_1 имеет «0» в положении [1,1] и male_1 имеет «1 "в позиции [1,1]. И из всех 5 столбцов в обоих наборах данных это единственное, где существует «несоответствие» между этой парой. Таким образом, есть общая ячейка «1», где это женское_1/male_1 попарное сравнение выполняет мое условие. Имеет ли это смысл? – pbc

+0

На самом деле это не «пересечение» в каком-то смысле, а скорее отображение в «пространство продукта». Две функции, которые обеспечивают результаты n-by-m для объектов-матриц, это 'outer' и' kronecker', но для правильной работы они требуют тонкой обработки кода для получения функций, которые обеспечивают результаты с правильными размерами. –

+0

Если я чего-то не хватает, 'ncol (females) - tcrossprod (! Females,! Males) - tcrossprod (as.matrix (females), as.matrix (мужчины))' кажется правильным –

ответ

1

Настройка объекта для получения результата:

xy <- matrix(NA, nrow(females), nrow(males)) 
for (x in 1:nrow(females)){ 
     for(y in 1:nrow(males)){ 
       xy[x,y] <- sum(females[x, 1:ncol(females)] != males[y,1:ncol(males)])}} 

Если бы сделать с вложенными sapply звонки, а также и, возможно, был немного чище, так как не было никакой необходимости иметь отдельный «настройки», (но только немного чище, и вопреки распространенному мифу не быстрее):

xy <- sapply(1:nrow(females) , 
       function(x) sapply(1:nrow(males) , 
        function(y) sum(females[x, 1:ncol(females)] != males[y,1:ncol(males)]))) 
xy 
#----- 
    [,1] [,2] [,3] [,4] [,5] 
[1,] 1 3 2 1 1 
[2,] 1 1 4 1 3 
[3,] 3 5 0 3 1 
[4,] 2 2 3 0 2 
[5,] 3 5 0 3 1 

dimnames(xy) <- list(rownames(females), rownames(males)) 
+0

Спасибо, @ 42-! Есть ли способ сохранить имена строк и столбцов (как в примере с крестиком), чтобы я мог использовать их позже? – pbc

+0

Довольно легко добавить dimnames в матрицу. См. Страницу справки для '? Dimnames', так как я уверен, что функция назначения также описана. Также можно было бы сделать это на шаге «настройка», если использовать метод for-loop. –

+0

Отлично @ 42-! Еще раз спасибо! – pbc

0
inverseCross <- function(females, males){ 
inverse <- data.frame(a=integer(), b=integer(), c=integer(), d=integer(), e=integer()) 
tempRow <- NULL 
for(i in 1:nrow(females)){ 
for(j in 1:nrow(males)){ 
sum <- 0 
for(k in 1: ncol(males)){ 
if(females[i,k] != males[j,k]){ 
sum <- sum + 1 
} 
} 
tempRow <- c(tempRow, sum) 
} 
inverse[i,] <- tempRow 
} 
colnames(inverse) <- rownames(males) 
rownames(inverse) <- rownames(females) 
inverse 
} 
+0

Я сомневаюсь, что это сработало в данный момент. В R синтаксически важны строки (или точки с запятой). –

+0

О, я протестировал его, это отлично работает –

+0

inverseCross <- function (женщины, мужчины) {inverse <- data.frame (a = integer(), b = integer(), c = integer(), d = integer(), e = integer()) для (i in 1: nrow (females)) { tempRow <- NULL для (j in 1: nrow (мужчины)) { sum <- 0 для (k in 1: ncol (мужчины)) { если (женщины [i, k]! = Мужчины [j, k]) { сумма <- сумма + 1 } } tempRow <- с (tempRow, сумма) } обратное [I,] <- tempRow } COLNAMES (обратный) <- rownames (самцы) rownames (обратный) <- имена (женщины) инверсные } –