Ich habe einen Datenrahmen wie folgt:
data.frame(director = c("Aaron Blaise,Bob Walker", "Akira Kurosawa",
"Alan J. Pakula", "Alan Parker", "Alejandro Amenabar", "Alejandro Gonzalez Inarritu",
"Alejandro Gonzalez Inarritu,Benicio Del Toro", "Alejandro González Iñárritu",
"Alex Proyas", "Alexander Hall", "Alfonso Cuaron", "Alfred Hitchcock",
"Anatole Litvak", "Andrew Adamson,Marilyn Fox", "Andrew Dominik",
"Andrew Stanton", "Andrew Stanton,Lee Unkrich", "Angelina Jolie,John Stevenson",
"Anne Fontaine", "Anthony Harvey"), AB = c('A', 'B', 'A', 'A', 'B', 'B', 'B', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'A'))
Wie Sie sehen können, sind einige Einträge in der director
Spalte mehrere durch Kommas getrennte Namen. Ich möchte diese Einträge in separate Zeilen aufteilen und dabei die Werte der anderen Spalte beibehalten. Als Beispiel sollte die erste Zeile im obigen Datenrahmen in zwei Zeilen aufgeteilt werden, mit jeweils einem Namen in der director
Spalte und 'A' in der AB
Spalte.
Antworten:
Diese alte Frage wird häufig als betrogenes Ziel verwendet (markiert mit
r-faq
). Bis heute wurde es dreimal mit 6 verschiedenen Ansätzen beantwortet, es fehlt jedoch ein Benchmark als Leitfaden, welcher der Ansätze der schnellste ist 1 .Die Benchmark-Lösungen umfassen
data.table
Methoden und zweidplyr
/tidyr
Ansätze,splitstackshape
Lösung ,data.table
Methoden.Insgesamt wurden 8 verschiedene Methoden mit dem
microbenchmark
Paket an 6 verschiedenen Datenrahmengrößen verglichen (siehe Code unten).Die vom OP angegebenen Beispieldaten bestehen nur aus 20 Zeilen. Um größere Datenrahmen zu erstellen, werden diese 20 Zeilen einfach 1, 10, 100, 1000, 10000 und 100000 Mal wiederholt, was zu Problemgrößen von bis zu 2 Millionen Zeilen führt.
Benchmark-Ergebnisse
Die Benchmark-Ergebnisse zeigen, dass bei ausreichend großen Datenrahmen alle
data.table
Methoden schneller sind als jede andere Methode. Für Datenrahmen mit mehr als etwa 5000 Zeilen sind Jaapsdata.table
Methode 2 und die VarianteDT3
die schnellsten, Größenordnungen schneller als die langsamsten Methoden.Bemerkenswerterweise sind die Zeitpunkte der beiden
tidyverse
Methoden und dersplistackshape
Lösung so ähnlich, dass es schwierig ist, die Kurven im Diagramm zu unterscheiden. Sie sind die langsamste der Benchmark-Methoden für alle Datenrahmengrößen.Bei kleineren Datenrahmen
data.table
scheinen Matts Basis-R-Lösung und Methode 4 weniger Overhead zu haben als die anderen Methoden.Code
Definieren Sie die Funktion für Benchmark-Läufe mit Problemgröße
n
Führen Sie einen Benchmark für verschiedene Problemgrößen aus
Bereiten Sie die Daten für das Plotten vor
Diagramm erstellen
Sitzungsinfo & Paketversionen (Auszug)
1 Meine Neugier wurde durch diesen üppigen Kommentar geweckt. Brilliant! Größenordnungen schneller! auf eine
tidyverse
Antwort auf eine Frage, die als Duplikat dieser Frage geschlossen wurde.quelle
data.table
,dplyr
usw.strsplit
fixed=TRUE
. Wie die anderen haben und dies wird Auswirkungen auf das Timing haben. Da R 4.0.0 , die Standardeinstellung , wenn ein zu schaffendata.frame
, iststringsAsFactors = FALSE
, soas.character
könnte entfernt werden.Mehrere Alternativen:
1) zwei Wege mit Datentabelle::
2) a dplyr /. tidyr Kombination:
3) mit tidyrnur: Mit
tidyr 0.5.0
(und später) können Sie auch nur verwendenseparate_rows
:Mit dem
convert = TRUE
Parameter können Sie Zahlen automatisch in numerische Spalten konvertieren.4) mit Basis R:
quelle
data.table(id= "X21", a = "chr1;chr1;chr1", b="123;133;134",c="234;254;268")
werdendata.table(id = c("X21","X21",X21"), a=c("chr1","chr1","chr1"), b=c("123","133","134"), c=c("234","254","268"))
?setDT(dt)[,lapply(.SD, function(x) unlist(tstrsplit(x, ";",fixed=TRUE))), by = ID]
hat bei mir funktioniert.Wenn Sie Ihren ursprünglichen data.frame benennen
v
, haben wir Folgendes :Beachten Sie die Verwendung von
rep
, um die neue AB-Spalte zu erstellen. Hier wirdsapply
die Anzahl der Namen in jeder der ursprünglichen Zeilen zurückgegeben.quelle
vapply
? Gibt es etwas, dasvapply
hier angemessener ist?sapply(s, length)
könnte durch ersetzt werdenlengths(s)
.Spät zur Party, aber eine andere verallgemeinerte Alternative ist die Verwendung
cSplit
aus meinem "splitstackshape" -Paket, das eindirection
Argument hat. Stellen Sie dies auf ein"long"
, um das von Ihnen angegebene Ergebnis zu erhalten:quelle
quelle
Ein weiterer Benchmark, der sich aus der Verwendung
strsplit
von base ergibt, könnte derzeit empfohlen werden, durch Kommas getrennte Zeichenfolgen in einer Spalte in separate Zeilen aufzuteilen , da dies über einen weiten Größenbereich der schnellste war:Beachten Sie, dass die Verwendung
fixed=TRUE
erhebliche Auswirkungen auf das Timing hat.Vergleichte Methoden:
Bibliotheken:
Daten:
Berechnungs- und Timing-Ergebnisse:
Beachten Sie, Methoden wie
Geben Sie ein
strsplit
fürunique
Regisseur zurück und könnte mit vergleichbar seinaber nach meinem Verständnis wurde dies nicht gefragt.
quelle