2016-04-13 32 views
6

Próbując wyodrębnić niedopasowania między dwiema poniższymi ramkami danych, udało mi się już utworzyć nową ramkę danych, w której zastępowane są niedopasowania.
Co muszę teraz jest lista niedopasowania:Jak porównać dwie ramki danych/tabele i wyodrębnić dane w R?

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 

celu wyjaśnienia rozbieżności, tutaj są one oznaczone jako 00 na:

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

muszę następujący wynik:

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 

Do tej pory próbowałem wyodrębnić dodatkowe dane z mojej funkcji lapply, której używam, aby zastąpić niedopasowania o zero, ale bez powodzenia. Próbowałem również napisać funkcję ifelse bez powodzenia. Mam nadzieję, że możecie mi pomóc tutaj!

Ostatecznie ten będzie prowadzony do zbiorów danych o wymiarze 100K przez 1000, więc wydajność jest pro

+1

Twój wyjaśnienie może wyprodukowany przez: 'ifelse (as.matrix (DFA) == as.matrix (DFB), as.matrix (DFA), "00")' – jogo

+0

Wykonaj rownames z 'dfA' zawsze pasuje do rownames 'dfB'? – lukeA

+0

@lukeA Tak, tworzę dwa podzestawy, w których zarówno nazwa wiersza, jak i kolumny będą zawsze zgodne. – Bas

Odpowiedz

6

To pytanie ma tag data.table, więc oto moja próba użycia tego pakietu. Pierwszym krokiem jest konwersja nazw wierszy do kolumn jako data.table, których nie lubisz, a następnie konwersja do formatu długiego po rbind i ustawianie identyfikatora dla każdego zestawu danych, znajdowanie tam, gdzie istnieje więcej niż jedna niepowtarzalna wartość i konwersja z powrotem na szeroki format

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 
4

Oto rozwiązanie przy użyciu array.indices macierzy:

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 
3

Można to zrobić za pomocą dplyr/tidyr, stosując podobne podejście, jak w poście @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