Как сравнить два фрейма данных / таблицы и извлечь данные в R?

в попытке извлечь несоответствия между двумя фреймами данных ниже Мне уже удалось создать новый фрейм данных, в котором несоответствия заменяются.
Теперь мне нужен список несоответствий:--6-->

dfA <- structure(list(animal1 = c("AA", "TT", "AG", "CA"), animal2 = c("AA", "TB", "AG", "CA"), animal3 = c("AA", "TT", "AG", "CA")), .Names = c("animal1", "animal2", "animal3"), row.names = c("snp1", "snp2", "snp3", "snp4"), class = "data.frame")
# > dfA
#      animal1 animal2 animal3
# snp1      AA      AA      AA
# snp2      TT      TB      TT
# snp3      AG      AG      AG
# snp4      CA      CA      CA
dfB <- structure(list(animal1 = c("AA", "TT", "AG", "CA"), animal2 = c("AA", "TB", "AG", "DF"), animal3 = c("AA", "TB", "AG", "DF")), .Names = c("animal1", "animal2", "animal3"), row.names = c("snp1", "snp2", "snp3", "snp4"), class = "data.frame")
#> dfB
#     animal1 animal2 animal3
#snp1      AA      AA      AA
#snp2      TT      TB      TB
#snp3      AG      AG      AG
#snp4      CA      DF      DF

чтобы уточнить несоответствия, здесь они отмечены как 00:

#      animal1 animal2 animal3
# snp1      AA      AA      AA
# snp2      TT      TB      00
# snp3      AG      AG      AG
# snp4      CA      00      00

мне нужен следующий вывод:

structure(list(snpname = structure(c(1L, 2L, 2L), .Label = c("snp2", "snp4"), class = "factor"), animalname = structure(c(2L, 1L, 2L), .Label = c("animal2", "animal3"), class = "factor"), alleledfA = structure(c(2L, 1L, 1L), .Label = c("CA", "TT"), class = "factor"), alleledfB = structure(c(2L, 1L, 1L), .Label = c("DF", "TB"), class = "factor")), .Names = c("snpname", "animalname", "alleledfA", "alleledfB"), class = "data.frame", row.names = c(NA, -3L))
#  snpname animalname alleledfA alleledfB
#1    snp2    animal3        TT        TB
#2    snp4    animal2        CA        DF
#3    snp4    animal3        CA        DF

до сих пор я пытался извлечь дополнительные данные из моего lapply функция, которую я использую для замены несоответствий ноль, но безуспешно. Я также попытался написать функцию ifelse без успеха. Надеюсь, вы мне поможете!

в конечном итоге это будет выполняться для наборов данных с размером 100K на 1000, поэтому эффективность является pro

3 ответов


этот вопрос data.table tag, поэтому вот моя попытка использовать этот пакет. Первый шаг-преобразовать имена строк в столбцы как data.table Не нравится, а затем преобразование в длинный формат после rbinding и установка идентификатора на набор данных, поиск, где есть более одного уникального значения и преобразование обратно в широкий формат

library(data.table)  
setDT(dfA, keep.rownames = TRUE) 
setDT(dfB, keep.rownames = TRUE)   

dcast(melt(rbind(dfA, 
                 dfB, 
                 idcol = TRUE), 
           id = 1:2
           )[, 
             if(uniqueN(value) > 1L) .SD, 
             by = .(rn, variable)], 
      rn + variable ~ .id)

#      rn variable  1  2
# 1: snp2  animal3 TT TB
# 2: snp4  animal2 CA DF
# 3: snp4  animal3 CA DF

вот решение с использованием массива.индексы матрицы:

i.arr <- which(dfA != dfB, arr.ind=TRUE)

data.frame(snp=rownames(dfA)[i.arr[,1]], animal=colnames(dfA)[i.arr[,2]],
           A=dfA[i.arr], B=dfB[i.arr])
#   snp  animal  A  B
#1 snp4 animal2 CA DF
#2 snp2 animal3 TT TB
#3 snp4 animal3 CA DF

Это можно сделать с помощью dplyr/tidyr используя аналогичный подход, как в сообщении @David Arenburg.

library(dplyr)
library(tidyr)
bind_rows(add_rownames(dfA), add_rownames(dfB)) %>% 
          gather(Var, Val, -rowname) %>%
          group_by(rowname, Var) %>%
          filter(n_distinct(Val)>1) %>% 
          mutate(id = 1:2) %>% 
          spread(id, Val)
#  rowname     Var     1     2
#    (chr)   (chr) (chr) (chr)
#1    snp2 animal3    TT    TB
#2    snp4 animal2    CA    DF
#3    snp4 animal3    CA    DF