Ich habe eine große Datentabelle mit vielen fehlenden Werten, die über die ~ 200.000 Zeilen und 200 Spalten verteilt sind. Ich möchte diese NA-Werte so effizient wie möglich auf Nullen umcodieren.
Ich sehe zwei Möglichkeiten:
1: Konvertieren zu einem data.frame und Verwendung etwas wie diese
2: Irgendeine Art von kühlem data.table Unterstellbefehl
Ich bin mit einer ziemlich effizienten Lösung vom Typ 1 zufrieden. Die Konvertierung in einen data.frame und dann zurück in eine data.table dauert nicht lange.
data.table
zu einemdata.frame
? Adata.table
ist adata.frame
. Jede data.frame-Operation funktioniert einfach.data.table
indem Sie die Spaltennummer angeben. soDT[,3]
wird nicht die dritte Spalte geben. Ich denke, dies macht die im Link vorgeschlagene Lösung hier unrentabel. Ich bin sicher, es gibt einen eleganten Ansatz mit etwasdata.table
Zauberei!DT[, 3, with=FALSE]
gibt die dritte Spalte zurück.mydf[is.na(mydf) == TRUE]
das die Arbeit an Datenrahmen erledigt, währendmydt[is.na(mydt) == TRUE]
es mir etwas Seltsames gibt, selbst wenn ich es benutzewith=FALSE
Antworten:
Hier ist eine Lösung mit data.table ‚s
:=
Operator, aufbauend auf Andrie und Ramnath der Antworten.Beachten Sie, dass f_dowle dt1 als Referenz aktualisiert hat. Wenn eine lokale Kopie erforderlich ist, ist ein expliziter Aufruf der
copy
Funktion erforderlich, um eine lokale Kopie des gesamten Datensatzes zu erstellen. data.table istsetkey
,key<-
und:=
nicht Copy-on-Write.Als nächstes wollen wir sehen, wo f_dowle seine Zeit verbringt.
Dort würde ich mich auf
na.replace
und konzentrierenis.na
, wo es ein paar Vektorkopien und Vektorscans gibt. Diese können ziemlich einfach beseitigt werden, indem eine kleine na.replace C-Funktion geschrieben wird, dieNA
durch Referenz im Vektor aktualisiert wird. Das würde mindestens die 20 Sekunden halbieren, denke ich. Existiert eine solche Funktion in einem R-Paket?Der Grund dafür
f_andrie
kann sein, dass einige Male das Ganze kopiertdt1
oder eine logische Matrix erstellt wird, die so groß wie das Ganzedt1
ist. Die anderen beiden Methoden arbeiten jeweils an einer Spalte (obwohl ich sie mir nur kurz angesehen habeNAToUnknown
).EDIT (elegantere Lösung, wie von Ramnath in Kommentaren gefordert):
Ich wünschte, ich hätte es so gemacht!
EDIT2 (über 1 Jahr später, jetzt)
Es gibt auch
set()
. Dies kann schneller sein, wenn viele Spalten durchlaufen werden, da der (geringe) Aufwand beim Aufrufen[,:=,]
einer Schleife vermieden wird.set
ist eine Schleife:=
. Siehe?set
.quelle
eval(parse)...
Zeug zu haben ? Im weiteren Sinne halte ich es für nützlich, Operationen zu haben, die auf allen Elementen desdata.table
.data.table
geeignete Weg zu sein, dies zu tun. Vielen Dank!DT
haben Spalten vom Typlogical
, im Gegensatz zumcreate_dt()
Beispiel für diesen Test. Ändern Sie das 4. Argument desset()
Aufrufs (0
in Ihrem Beispiel und geben Sie double in R ein) inFALSE
und es sollte ohne Warnung funktionieren.seq_along(DT)
auch. Aber dann muss der Leser wissen, dassseq_along
dies entlang der Spalten und nicht entlang der Zeilen erfolgt.seq_len(col(DT))
ein kleines bisschen expliziter aus diesem Grund.Hier ist die einfachste, die ich mir vorstellen kann:
dt[is.na(dt)] <- 0
Es ist effizient und es müssen keine Funktionen und kein anderer Klebercode geschrieben werden.
quelle
[.data.table
(dt, is.na (dt)): i ist ein ungültiger Typ (Matrix). Vielleicht könnte eine 2-Spalten-Matrix in Zukunft eine Liste von DT-Elementen zurückgeben (im Sinne von A [B] in FAQ 2.14). Bitte teilen Sie datatable-help mit, ob Sie dies möchten, oder fügen Sie Ihre Kommentare zu FR # 657 hinzu. >set
Spezielle Funktionen (
nafill
undsetnafill
) für diesen Zweck sind imdata.table
Paket verfügbar (Version> = 1.12.4):Es verarbeitet Spalten parallel, um zuvor veröffentlichte Benchmarks so gut zu adressieren, dass sie unter den Zeitpunkten im Vergleich zum bisher schnellsten Ansatz liegen, und skaliert sie auch mithilfe einer 40-Kerne-Maschine.
quelle
Nur als Referenz, langsamer im Vergleich zu gdata oder data.matrix, verwendet jedoch nur das Paket data.table und kann nicht numerische Einträge verarbeiten.
quelle
ifelse
als auch durch Referenz aktualisierenDT[, names(DT) := lapply(.SD, function(x) {x[is.na(x)] <- "0" ; x})]
. Und ich bezweifle, dass es langsamer sein wird als die Antworten, die Sie erwähnt haben.Hier ist eine Lösung, die
NAToUnknown
imgdata
Paket verwendet wird. Ich habe Andries Lösung verwendet, um eine riesige Datentabelle zu erstellen, und auch Zeitvergleiche mit Andries Lösung aufgenommen.quelle
user
Zeit, aber wirklich großem Zeitunterschied seheelapsed
.rbenchmark
, Lösungen mit mehr Replikationen zu vergleichen, habe jedoch möglicherweise aufgrund der Größe des Datenrahmens einen Speicherfehler festgestellt . Wenn Siebenchmark
beide Lösungen mit mehreren Replikationen ausführen können, wären diese Ergebnisse interessant, da ich nicht sicher bin, warum ich eine dreifache Beschleunigung erhaltencol=5
meiner Meinung nach (sollte viel länger dauern) aufgrund des Fehlers increate_dt
.Der Vollständigkeit halber können Sie NAs auch durch 0 ersetzen
Um Ergebnisse und Zeiten zu vergleichen, habe ich alle bisher genannten Ansätze berücksichtigt.
Der neue Ansatz ist also etwas langsamer als,
f_dowle3
aber schneller als alle anderen Ansätze. Aber um ehrlich zu sein, ist dies gegen meine Intuition der data.table-Syntax und ich habe keine Ahnung, warum dies funktioniert. Kann mich jemand aufklären?quelle
Mein Verständnis ist, dass das Geheimnis schneller Operationen in R darin besteht, Vektoren (oder Arrays, die Vektoren unter der Haube sind) zu verwenden.
In dieser Lösung verwende ich ein,
data.matrix
das ein istarray
, sich aber ein bisschen wie ein verhaltedata.frame
. Da es sich um ein Array handelt, können Sie eine sehr einfache Vektorsubstitution verwenden, um dasNA
s zu ersetzen :Eine kleine Hilfsfunktion zum Entfernen des
NA
s. Die Essenz ist eine einzelne Codezeile. Ich mache das nur, um die Ausführungszeit zu messen.Eine kleine Hilfsfunktion zum Erstellen
data.table
einer bestimmten Größe.Demonstration an einer winzigen Probe:
quelle
remove_na
. Dieser Zeitpunkt von 21,57 Sekunden beinhaltet dascreate_dt
(einschließlichrunif
undsample
) zusammen mit demremove_na
. Gibt es eine Chance, die Sie bearbeiten könnten, um die 2-mal aufzuteilen?create_dt
? Es scheint immer eine 5-Spalten-Datentabelle zu erstellen, unabhängig davon, ob siencol
übergeben wurde.Um auf viele Spalten zu verallgemeinern, können Sie diesen Ansatz verwenden (unter Verwendung vorheriger Beispieldaten, aber Hinzufügen einer Spalte):
Ich habe die Geschwindigkeit allerdings nicht getestet
quelle
quelle
Mit der
fifelse
Funktion aus den neuestendata.table
Versionen 1.12.6 ist sie sogar zehnmal schneller alsNAToUnknown
imgdata
Paket:quelle
f_dowle3
wird noch schneller gehen: stackoverflow.com/a/7249454/345660