Как объединить матрицы по имени строки и вставить пустое место в несовпадающие элементы в R?

Я хочу объединить две матрицы с частично перекрывающимися именами строк в R. Когда имена строк совпадают, значения из двух матриц должны оказаться в виде соседних столбцов. Когда имена строк встречаются только в одной матрице, для другой матрицы должно быть вставлено пустое место.

Набор данных:

testm1 <- cbind("est"=c(1.5,1.2,0.7,4.0), "lci"=c(1.1,0.9,0.5,0.9), "hci"=c(2.0,1.7,0.8,9.0))
rownames(testm1) <- c("BadFood","NoActivity","NoSunlight","NoWater")
testm1 #Factors associated with becoming sick
testm2 <- cbind("est"=c(3.0,2.0,0.9,7.0), "lci"=c(1.3,1.2,0.2,2.0), "hci"=c(5.0,3.1,1.7,9.0))
rownames(testm2) <- c("BadFood","NoActivity","Genetics","Age")
testm2 #Factors associated with dying

Желаемый результат:

           Sick        Dying
           est lci hci est lci hci
BadFood    1.5 1.1 2.0 3.0 1.3 5.0
NoActivity 1.2 0.9 1.7 2.0 1.2 3.1
NoSunlight 0.7 0.5 0.8 -   -   -
NoWater    4.0 0.9 9.0 -   -   -
Genetics   -   -   -   0.9 0.2 1.7
Age        -   -   -   7.0 2.0 9.0

Есть ли простой способ сделать это, который будет работать для всех матриц?


person CarlAH    schedule 30.06.2016    source источник
comment
Расстроился из-за -1. Слишком простой вопрос, чтобы задать его в stackoverflow?   -  person CarlAH    schedule 30.06.2016


Ответы (3)


Вот базовый метод R, который сохраняет все в матричной форме:

# get rownames of new matrix
newNames <- union(rownames(testm1), rownames(testm2))
# construct new matrix
newMat <- matrix(NA, length(newNames), 2*ncol(testm2),
                 dimnames=list(c(newNames), rep(colnames(testm1), 2)))
# fill in new matrix
newMat[match(rownames(testm1), newNames), 1:ncol(testm1)] <- testm1
newMat[match(rownames(testm2), newNames), (ncol(testm1)+1):ncol(newMat)] <- testm2

В последних двух строках match используется для поиска правильных индексов строк по имени строки.

Это возвращает

newMat
           est lci hci est lci hci
BadFood    1.5 1.1 2.0 3.0 1.3 5.0
NoActivity 1.2 0.9 1.7 2.0 1.2 3.1
NoSunlight 0.7 0.5 0.8  NA  NA  NA
NoWater    4.0 0.9 9.0  NA  NA  NA
Genetics    NA  NA  NA 0.9 0.2 1.7
Age         NA  NA  NA 7.0 2.0 9.0
person lmo    schedule 30.06.2016
comment
Дал согласие на это, потому что он сделал все, что я хотел - person CarlAH; 30.06.2016

Я думаю, что это делает то, что вам нужно, хотя это не так красиво и требует, чтобы данные были data.frame, а не матрицей. Надеюсь хоть поможет! (Код был адаптирован из этого вопроса и ответа https://stackoverflow.com/a/34530141/4651564)

library(dplyr)
dat1 <- as.data.frame(testm1)
dat2 <- as.data.frame(testm2)
full_join(   dat1 %>% mutate(Symbol = rownames(dat1)  ),
             dat2 %>% mutate(Symbol = rownames(dat2)  ),
             by = 'Symbol')
person gowerc    schedule 30.06.2016
comment
Это решение кажется изящным, но функция full_join не была найдена на моем компьютере, несмотря на установку dplyr. Этот код работал для вас, когда вы его запускали? - person CarlAH; 30.06.2016
comment
Какая версия dplyr у вас установлена? full_join был добавлен в версию 0.4.0 9 января 2015 г. ref - person gowerc; 30.06.2016
comment
Аааа, это объясняет. Была установлена ​​версия 0.2. - person CarlAH; 30.06.2016

Вы можете сделать это с помощью функции merge(). Прежде всего, вставьте свои тестовые матрицы в фреймы данных, затем используйте слияние в фреймах данных, наконец, преобразуйте результат в матрицу (но вам обязательно нужна матрица?). Вот пример кода:

testm1 <- as.data.frame(testm1)
testm2 <- as.data.frame(testm2)
result <- merge(testm1, testm2, by='row.names', all.x=T, all.y=T)
# all.x is needed if you want to save rows not matched in the merge process
result <- as.matrix(result)

Если вы хотите получить фрейм данных, просто опустите последнюю строку кода. Надеюсь это поможет.

person Eugen    schedule 30.06.2016
comment
Это сработало для меня. Единственная проблема в том, что порядок строк немного беспорядочный - person CarlAH; 30.06.2016
comment
Да, я предположил, что порядок строк не важен... вы можете изменить порядок строк, работая с аргументами функции. Но у вас есть причина, я должен был подумать об этом раньше :) - person Eugen; 30.06.2016