2012-06-09 10 views
5

Mam data.frame z 1000 wierszy i 3 kolumny. Zawiera dużą liczbę duplikatów, a ja użyłem plyr, aby połączyć duplikaty wierszy i dodać liczbę dla każdej kombinacji, jak wyjaśniono w this thread.Zlokalizuj i scal duplikaty wierszy w data.frame, ale ignoruj ​​kolejność kolumn

Oto przykład tego, co mam teraz (I nadal mieć oryginalną data.frame ze wszystkich duplikatów czy muszę zacząć stamtąd):

name1 name2 name3  total 
1 Bob  Fred  Sam  30 
2 Bob  Joe  Frank  20 
3 Frank Sam  Tom  25 
4 Sam  Tom  Frank  10 
5 Fred  Bob  Sam  15 

Jednak kolejność kolumn nie materia. Chcę tylko wiedzieć, ile wierszy ma te same trzy wpisy, w dowolnej kolejności. Jak mogę połączyć wiersze zawierające te same wpisy, ignorując zamówienie? W tym przykładzie chciałbym połączyć wiersze 1 i 5 oraz wiersze 3 i 4.

Odpowiedz

4

Zdefiniuj kolejną kolumnę, która jest "posortowaną pastą" z nazwami, które miałyby taką samą wartość "Bob ~ Fred ~ Sam" dla wierszy 1 i 5. Następnie agreguj na tej podstawie.

Krótki fragment kodu (zakłada oryginalną ramkę danych to dd): to wszystko jest naprawdę intuicyjne. Tworzymy kolumnę lookup (Spójrz i powinna być oczywista), uzyskać sumy kolumny total dla każdej kombinacji, a następnie filtrować w dół do unikalnych kombinacjach ...

dd$lookup=apply(dd[,c("name1","name2","name3")],1, 
            function(x){paste(sort(x),collapse="~")}) 
tab1=tapply(dd$total,dd$lookup,sum) 
ee=dd[match(unique(dd$lookup),dd$lookup),] 
ee$newtotal=as.numeric(tab1)[match(ee$lookup,names(tab1))] 

masz teraz w ee zestaw unikalnych wierszy i odpowiadające im liczby całkowite. Łatwe - i żadne pakiety zewnętrzne nie są potrzebne. I co najważniejsze, na każdym etapie procesu widać, co się dzieje!

(Minor aktualizacja pomóc OP :) A jeśli chcesz wersję oczyszczone-up ostatecznej odpowiedzi:

outdf = with(ee,data.frame(name1,name2,name3, 
          total=newtotal,stringsAsFactors=FALSE)) 

Daje to schludny ramkę danych z trzech najważniejszy kolumnach imię, a z zagregowanymi sumami w kolumnie o nazwie total zamiast newtotal.

+0

To również działało (po usunięciu spacji z wpisów data.frame). Eliminuje to również krok ręcznego kopiowania/wklejania danych. Jednak to pozostawia mnie: 'nazwa1 nazwa2 NAME3 całkowity odnośnika newtotal' 1 Sam Bob Fred 30 Fred Bob ~ ~ Sam 45 2 Bob Joe Frank 20 Bob ~ Frank ~ Joe 20 3 Frank Sam Tom 25 Frank ~ Sam ~ Tom 35' – jdfinch3

+0

Hmmm, nie można uzyskać bloku kodu do pracy w komentarzach ... jednak ee wyświetla połączone wyniki bez zaktualizowanych sum, a następnie obok połączonych wyników ze zaktualizowanymi sumami (i z ~ zamianą zakładki między wierszami). Jestem pewien, że jest to łatwa poprawka, ale nie wiem wystarczająco dobrze (jeszcze), aby ją łatwo naprawić ... – jdfinch3

+0

OK, rzeczywiście poświęciłem czas na przeczytanie twojego kodu i pomyśl o każdej akcji i zdałem sobie sprawę, że odpowiedź na moje pytanie była jeszcze bardziej oczywista, niż myślałem. Właśnie wziąłem dwie nowe kolumny i wstawiłem je do nowego data.frame (i zastąpiłem "~" przez "" tylko po to, aby ułatwić czytanie). Dzięki! – jdfinch3

4

Sortuj indeks kolumny, a następnie użyć ddply do agregowania i suma:

Określ dane:

dat <- " name1 name2 name3  total 
1 Bob  Fred  Sam  30 
2 Bob  Joe  Frank  20 
3 Frank Sam  Tom  25 
4 Sam  Tom  Frank  10 
5 Fred  Bob  Sam  15" 

x <- read.table(text=dat, header=TRUE) 

utworzyć kopię:

xx <- x 

Zastosowanie apply na sortowanie, następnie agreguj:

xx[, -4] <- t(apply(xx[, -4], 1, sort)) 
library(plyr) 
ddply(xx, .(name1, name2, name3), numcolwise(sum)) 
    name1 name2 name3 total 
1 Bob Frank Joe 20 
2 Bob Fred Sam 45 
3 Frank Sam Tom 35 
+0

Czy robienie tego w ten sposób nie zmieniło oryginalnych danych? Pierwsza linia mówiła "Bob, Fred, Sam" ...? –

+1

@timp Tak, ale ponieważ PO powiedział, że kolejność nie ma znaczenia, to prawdopodobnie nie ma znaczenia. W każdym razie oryginalne dane nadal znajdują się w 'x'. Dlatego stworzyłem nowy obiekt 'xx'. Ale powodem, dla którego kolejność rzędów jest inna, jest to, że 'ddply' sortuje zmienne grupujące przed wykonaniem agregacji. – Andrie

+1

Eek! Właśnie dlatego staram się oderwać od tych nowo sfałszowanych paczek - zawsze uważam, że naprawdę musisz je znać na wylot, w przeciwnym razie możesz łatwo zostać spalonym. Z drugiej strony, przypuszczam, że czasami nie miałbyś nic przeciwko temu, że twoje wiersze zostały zmienione (chociaż byłoby to koszmarem dla tego, do czego używam R). Dziękuję za porady :) –

Powiązane problemy