2012-07-30 22 views
9

Mam ramki danych miejsc aminokwasów i chcę utworzyć nową ramkę danych każdej pary kombinacji tych witryn.Wklej razem każdą parę kolumn w ramce danych w R?

Oryginalne dane będą wyglądać następująco:

df<-cbind(letters[1:5], letters[6:10], letters[11:15]) 
df 
[,1] [,2] [,3] 
[1,] "a" "f" "k" 
[2,] "b" "g" "l" 
[3,] "c" "h" "m" 
[4,] "d" "i" "n" 
[5,] "e" "j" "o" 

A co chciałbym to:

newdf<-cbind(paste(df[,1],df[,2],sep=""),paste(df[,1],df[,3],sep=""),(paste(df[,2],df[,3],sep=""))) 
newdf 
    [,1] [,2] [,3] 
[1,] "af" "ak" "fk" 
[2,] "bg" "bl" "gl" 
[3,] "ch" "cm" "hm" 
[4,] "di" "dn" "in" 
[5,] "ej" "eo" "jo" 

Rzeczywiste dane mogą mieć setki wierszy i/lub kolumn, więc oczywiście Potrzebuję mniej ręcznego sposobu robienia tego. Każda pomoc jest doceniana, jestem tylko skromnym biologiem, a moje umiejętności w tym zakresie są raczej ograniczone.

+0

Czy chcesz mieć tylko pary w tej samej kolejności, co ramka danych? To znaczy, dlaczego w pierwszym rzędzie nie ma "fa" lub "ka"? –

+0

Dzięki, kolejność nie jest ważna pod względem tożsamości, tj. "Fa" = "af", ale tak, pary powinny być w tej samej kolejności, co ramka danych, tak jak w przykładzie –

Odpowiedz

12

Połączenie combn() i apply() dostaniesz wszystkich nieuporządkowanych par combo:

df <- cbind(letters[1:5], letters[6:10], letters[11:15]) 

apply(X = combn(seq_len(ncol(df)), 2), 
     MAR = 2, 
     FUN = function(jj) { 
      apply(df[, jj], 1, paste, collapse="") 
     }  
) 
#  [,1] [,2] [,3] 
# [1,] "af" "ak" "fk" 
# [2,] "bg" "bl" "gl" 
# [3,] "ch" "cm" "hm" 
# [4,] "di" "dn" "in" 
# [5,] "ej" "eo" "jo" 

(Jeśli to, co się dzieje na powyższe nie jest od razu jasne, warto rzucić okiem na obiekt zwrócony przez combn(seq_len(ncol(df)), 2). Jej kolumny wyliczyć wszystkie nieuporządkowane combo parach liczb całkowitych między 1 i n, gdzie n jest liczba kolumn w ramce danych.)

+0

+1 Zaledwie niewiele mnie do tego! Usunięte miny –

+0

Dziękuję bardzo - to jest dokładnie to, czego potrzebowałem. Dlaczego nie wysłałem tego pytania pięć godzin temu? Wszyscy jesteście świetni. –

9

można użyć FUN argument combn wkleić razem kolumny z każdej kombinacji:

combn(ncol(df),2,FUN=function(i) apply(df[,i],1,paste0,collapse="")) 
+1

+1 Słodki i słodko obfuskowany do startu! –

+0

@ JoshO'Brien: co jest w tym ukryte? Argument 'FUN' dla' combn' może wydawać się nieco dziwny, ale jest bardzo przydatny, jeśli istnieje wiele kombinacji, ponieważ nie musisz przechowywać ich wszystkich w obiekcie pośrednim. –

+1

@otherJosh - Niewyjaśnione słowo prawdopodobnie było błędem. "Kompaktowy" byłby lepszy. Jako sam "pokorny biolog", po prostu zwracałem uwagę na to, jak trudno jest to przeanalizować (i moja odpowiedź w tej sprawie) dla OP. (Żeby było jasne, nadal jestem biologiem - po prostu już nie jestem skromny ...;) –

2

Josh i odpowiedzi Joshua są lepsze, ale pomyślałem, że dam moje podejście:

Wymaga to z pobraniem qdap varsion 1.1.0 pomocą paste2 funkcję:

library(qdap) 

ind <- unique(t(apply(expand.grid(1:3, 1:3), 1, sort))) 
ind <- ind[ind[, 1] != ind[, 2], ] 
sapply(1:nrow(ind), function(i) paste2(df[, unlist(ind[i, ])], sep="")) 

Mimo to, aby wykraść z ich odpowiedzi, będzie to znacznie bardziej czytelne:

ind <- t(combn(seq_len(ncol(df)), 2)) 
sapply(1:nrow(ind), function(i) paste2(df[, unlist(ind[i, ])], sep="")) 
-1

Pamiętaj, że dostaniesz dużo kolumn w nowym data.frame, skoro mówisz, że mają setki kolumn w oryginalnym data.frame: czy oryginalne dane zawierają n kolumny, a następnie nowy jeden będzie zawierał kolumny n (n-1)/2 - to skaluje się kwadraturowo.

+3

To nie jest odpowiedź; powinieneś dodać to jako komentarz do pytania. –

+0

Po prostu próbowałem zmienić to na komentarz. Jednak z tym małym przedstawicielstwem wydaje mi się, że nie mogę jeszcze komentować pytań. Czy to ma sens, aby ktoś inny zamienił to w komentarz, czy może przekroczyłby linię do spamu? –

Powiązane problemy