2016-10-03 5 views
1

Ich habe mehrere Datenrahmen in R mit genau der gleichen Struktur, und ich möchte sie vertikal in einem einzigen Datenrahmen zusammenführen. unsplit() scheint wie eine richtige Funktion zu tun. Ich war jedoch nicht in der Lage, es zum Laufen zu bringen.Wie verwenden Sie unsplit(), um mehrere Datenrahmen vertikal zu verbinden?

Schließlich reduzierte ich alles auf diesen einfachen Fall:

> df <- data.frame("ch" = c("A", "B"), "num" = c(1, 2)); 
> df 
    ch num 
1 A 1 
2 B 2 


> divided <- split(df, df$ch); 
> divided 
$A 
    ch num 
1 A 1 

$B 
    ch num 
2 B 2 


> changed <- lapply(divided, function (x) {data.frame("ch" = x$ch, "num" = x$num + 1)}) 
> changed 
$A 
    ch num 
1 A 2 

$B 
    ch num 
1 B 3 


> unsplit(changed, df$ch) 
Error in `row.names<-.data.frame`(`*tmp*`, value = value) : 
    duplicate 'row.names' are not allowed 
In addition: Warning message: 
non-unique value when setting 'row.names': ‘1’ 

So ist die Frage - warum in diesem Fall nicht unsplit() hat funktioniert? Was wäre ein richtiger Weg, diese Funktion zu nutzen?

P.S. Ich bin in der Lage, meine Aufgabe zu lösen, indem ich do.call('rbind', changed) benutze, aber diese Frage ist über korrekte Anwendung von unsplit().

+2

Lesen Sie den Fehler: Sie haben doppelte Zeilennamen, die 'unsplit' zur Rekombination verwendet. Aus '? Unsplit':" Im Datenrahmenfall werden Zeilennamen erhalten, indem die Zeilennamenvektoren von den Elementen von 'value' getrennt werden." – alistaire

+0

Danke @alistaire - Ich habe versucht, alles zu entschlüsseln, aber es ist wie in ein rekursives Kaninchen Loch gehen - unsplit() -> Elemente -> Zeilennamen -> unsplit() ... Und die Nachricht, die '* tmp * erwähnt 'Wert war auch nicht hilfreich (Ich weiß nicht, ob es eine Zeichenfolge oder ein Platzhalter in der Fehlerausgabe ist ...). Den Weg zu finden, den Fehler zu beheben und eine klare Erklärung dafür zu erhalten, welche Dateneinträge mit welchen Funktionen kollidieren, wäre großartig. –

+0

Es lohnt sich nicht zu reparieren; 'unsplit' ist eine meist nutzlose Funktion, da ohne signifikantes Finging nur etwas Split 'Split' möglich ist. 'do.call (rbind, ...)' ist der allgemeine Weg, um eine Liste von data.frames in R zu rekombinieren, obwohl dplyr und data.table die leistungsfähigeren Alternativen 'bind_rows' und' rbindlist' haben. – alistaire

Antwort

1

1) nach Splitting, num inkrementieren, ohne den Komponentendatenrahmen von Grunde auf wie dieses zu Rekonstruieren:

L <- lapply(divided, transform, num = num+1) 

Dann unsplit funktioniert:

> unsplit(L, df$ch) 
    ch num 
1 A 2 
2 B 3 

2) Wenn Sie die Datenrahmen von Grund auf neu rekonstruieren müssen, aber die Anzahl der Zeilen die gleiche in jeder Komponente halten dann die ursprünglichen Zeilennamen verwenden. Hier ist Ihr Code, außer dass wir row.names= hinzugefügt haben. Jetzt funktioniert es:

changed2 <- lapply(divided, 
    function (x) data.frame(ch = x$ch, num = x$num + 1, row.names = rownames(x))) 
unsplit(changed2, df$ch) 

3) Wenn Sie den Datenrahmen zu rekonstruieren, so dass es mehr Zeilen, dann müssen Sie neue einzigartige Reihe Namen synthetisieren, wie zum Beispiel in @ Mark Peterson-Lösung.

+0

Danke für das vollständige Bild der verschiedenen Methoden, wie dieses Problem zu lösen. BTW - wie funktioniert 'num = num + 1' im ersten Fall? Ich erwarte, dass die übergebenen Argumente von R berechnet werden, bevor sie die Funktion tatsächlich ausführen. Also sagt 'num = num + 1' etwas wie" nimm die Variable 'num', füge 1 hinzu und übergebe es dann als Parameter mit dem Namen" num "an die Funktion. Aber zu diesem Zeitpunkt ist die Variable' num' nicht definiert daher ist es nicht möglich, 1 zu addieren ... Und deshalb würde ich außer sehen, einen Fehler zu sehen, wenn ich diesen Funktionsaufruf mache. –

+0

(1) ist äquivalent zu 'lapply (geteilt, Funktion (x) transformiere (x, num = num + 1)) '. Siehe' 'transform' für weitere Informationen. –

+0

Ich kann spekulieren, wie das letztere Äquivalent funktionieren könnte - es gibt ein Lambda mit Abschluss, und' num' kann dort durch einen höheren Kontext eingeführt werden (obwohl R ist eine statische Kontextsprache, nicht dynamisch - so ist es noch unklar, wie "num" dort ankommt, weil es nirgendwo in den Umrahmungen des Aufrufs definiert ist. Aber für das ursprüngliche Beispiel aus (1) ist der Sprachmechanismus nicht Klar, wahrscheinlich muss ich die Spezifikation der Sprachsyntax genauer lesen. –

1

Sie müssen manuell die rownames überschreiben die „doppelte rownames“ Fehler zu vermeiden, zB ,:

changed <- lapply(divided, function (x) { 
    temp <- data.frame("ch" = x$ch, "num" = x$num + 1) 
    row.names(temp) <- 
    paste(x$ch, 1:nrow(x), sep = ".") 

    return(temp) 
    }) 

unsplit(changed, df$ch) 

Als Neben Besuche bind_rows von dplyr als Alternative do.call zu verwenden, die Sie machen können bereite weg nur zu Fuß von unsplit

+0

Cool, wird die Lösung debuggen. Sie sagen also, das Problem sei, dass 'dividiert' von' split() 'gebildet wurde, das jeder Zeile des neuen Datenrahmens" labels "- Zeilennamen aus der" df "-Struktur zugewiesen hat. Und damit ist 'unsplit()' in der Lage, die Datenrahmen wieder von "geteilt" zu kombinieren, da alle Zeilennamen eindeutig sind. Das ist aber nicht der Fall für 'changed' ... Ok ... Das scheint ein Verbesserungsbedarf in der' unsplit() 'Funktion zu sein, denn in der Mehrzahl der Fälle muss man die Labels nicht behalten, sondern er muss nur die Zeilen zusammenführen und ihre Namen neu indizieren. –

+0

Ich würde argumentieren, dass es da draußen genug bessere Werkzeuge gibt, dass es wenig Gründe gibt, das Verhalten von 'unsplit' zu ändern. Ich bin mir nicht sicher, dass es Fälle gibt, in denen das Verhalten' bind_rows' oder sogar 'do.call (rbind, listOfDFs) ' –

Verwandte Themen