2012-06-09 4 views
5

Ich habe ein data.frame mit 1.000 Zeilen und 3 Spalten. Es enthält eine große Anzahl von Duplikaten und ich habe plyr verwendet, um die doppelten Zeilen zu kombinieren und eine Zählung für jede Kombination hinzuzufügen, wie in this thread erklärt.Suchen Sie doppelte Zeilen in einem dat.frame, aber ignorieren Sie die Spaltenreihenfolge

Hier ist ein Beispiel dafür, was ich jetzt habe (ich mit all den Duplikaten auch noch die ursprüngliche data.frame, wenn ich von dort aus starten müssen):

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 

Allerdings ist Spaltenreihenfolge nicht Angelegenheit. Ich möchte nur wissen, wie viele Zeilen die gleichen drei Einträge haben, in beliebiger Reihenfolge. Wie kann ich die Zeilen, die die gleichen Einträge enthalten, kombinieren und dabei die Reihenfolge ignorieren? In diesem Beispiel würde ich die Zeilen 1 und 5 und die Zeilen 3 und 4 kombinieren wollen.

Antwort

4

Definieren Sie eine weitere Spalte, die eine "sortierte Paste" der Namen ist, die den gleichen Wert von "Bob ~ Fred ~ Sam" hätten für die Zeilen 1 und 5. Dann aggregieren Sie basierend darauf.

Kurze Code-Schnipsel (nimmt an, dass der ursprüngliche Datenrahmen dd ist): es ist alles wirklich intuitiv. Wir schaffen eine lookup Spalte (werfen Sie einen Blick und sollte selbsterklärend sein), erhalten die Summen der total Spalte für jede Kombination, und dann filtern bis zu den einzigartigen Kombinationen ...

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))] 

Sie haben jetzt in ee eine Reihe von eindeutigen Zeilen und ihre entsprechenden Gesamtanzahl. Einfach - und keine externen Pakete benötigt. Und vor allem können Sie in jedem Stadium des Prozesses sehen, was vor sich geht!

(Minor Update OP zu helfen :) Und wenn Sie möchten, eine aufgeräumte Version der endgültigen Antwort:

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

Dies gibt Ihnen eine saubere Datenrahmen mit den drei allen wichtigen Namen Spalten, und mit den aggregierten Summen in einer Spalte namens total statt newtotal.

+0

Dies funktionierte auch (nachdem ich Leerzeichen aus data.frame-Einträgen entfernt hatte). Außerdem entfällt der Schritt zum manuellen Kopieren/Einfügen von Daten. Aber es lässt mich mit: 'name1 name2 name3 Gesamt Lookup newtotal' 1 Bob Fred Sam 30 Bob ~ Fred ~ Sam 45 2 Bob Joe Frank 20 Bob ~ Frank ~ Joe 20 3 Frank Sam Tom 25 Frank ~ Sam ~ Tom 35' – jdfinch3

+0

Hmmm, kann Code-Block nicht in Kommentaren arbeiten ... jedoch zeigt ee die zusammengeführten Ergebnisse ohne die aktualisierten Summen und dann daneben die zusammengeführten Ergebnisse mit den aktualisierten Summen (und mit ~ ersetzen die Tabs zwischen Zeileneinträgen). Ich bin mir sicher, dass dies eine einfache Lösung ist, aber ich kenne R nicht gut genug, um es einfach zu reparieren ... – jdfinch3

+0

Ok, ich habe mir wirklich die Zeit genommen, deinen Code durchzulesen und jede Handlung zu durchdenken und erkannte, dass die Antwort auf meine Frage noch offensichtlicher war, als ich gedacht hatte. Ich nahm nur die zwei neuen Spalten und fügte sie in einen neuen data.frame ein (und ersetzte das "~" durch "", nur um es leichter zu lesen). Vielen Dank! – jdfinch3

4

Sortieren der Indexspalten, dann ddply aggregieren und Summe verwenden:

Definieren Sie die Daten:

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) 

Erstellen Sie eine Kopie:

xx <- x 

Verwenden apply sortieren Sie die Spalten, dann Aggregat:

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

Hat es nicht auf diese Weise die ursprünglichen Daten geändert? Die erste Zeile sagte "Bob, Fred, Sam" ...? –

+1

@timp Ja, aber da das OP sagte, dass die Reihenfolge keine Rolle spielt, ist das wahrscheinlich egal. Wie auch immer, die Originaldaten sind immer noch in "x". Deshalb habe ich ein neues Objekt 'xx' erstellt. Der Grund dafür, dass die Reihenfolge der Zeilen unterschiedlich ist, liegt darin, dass "ddply" die Gruppierungsvariablen vor der Aggregation sortiert. – Andrie

+1

Eek! Deshalb tendiere ich dazu, diese neumodischen Pakete zu meiden - ich finde immer, dass du sie wirklich von innen heraus kennen musst, sonst kannst du dich leicht verbrennen. Andererseits denke ich manchmal, dass es dir nichts ausmacht, wenn deine Reihen neu geordnet werden (obwohl das ein Albtraum für die Dinge wäre, für die ich R verwende). Danke für die Tipps aber :) –

Verwandte Themen