Wann sollte man a verwenden data.frame
und wann ist es besser, a zu verwenden matrix
?
Beide halten Daten in einem rechteckigen Format, so dass es manchmal unklar ist.
Gibt es allgemeine Faustregeln für die Verwendung des Datentyps?
Wann sollte man a verwenden data.frame
und wann ist es besser, a zu verwenden matrix
?
Beide halten Daten in einem rechteckigen Format, so dass es manchmal unklar ist.
Gibt es allgemeine Faustregeln für die Verwendung des Datentyps?
Antworten:
Ein Teil der Antwort ist bereits in Ihrer Frage enthalten: Sie verwenden Datenrahmen, wenn erwartet werden kann, dass Spalten (Variablen) unterschiedlichen Typs sind (numerisch / Zeichen / logisch usw.). Matrizen sind für Daten des gleichen Typs.
Folglich ist die Auswahlmatrix / der Datenrahmen nur dann problematisch, wenn Sie Daten desselben Typs haben.
Die Antwort hängt davon ab, was Sie mit den Daten in data.frame / matrix tun werden. Wenn es an andere Funktionen übergeben werden soll, bestimmt der erwartete Typ der Argumente dieser Funktionen die Auswahl.
Ebenfalls:
Matrizen sind speichereffizienter:
m = matrix(1:4, 2, 2)
d = as.data.frame(m)
object.size(m)
# 216 bytes
object.size(d)
# 792 bytes
Matrizen sind eine Notwendigkeit, wenn Sie Operationen vom Typ der linearen Algebra ausführen möchten.
Datenrahmen sind praktischer, wenn Sie häufig nach Namen auf ihre Spalten verweisen (über den kompakten Operator $).
Datenrahmen eignen sich meiner Meinung nach auch besser zum Melden (Drucken) von Tabelleninformationen, da Sie die Formatierung für jede Spalte separat anwenden können.
Von @Michal nicht erwähnt, ist, dass nicht nur eine Matrix kleiner als der entsprechende Datenrahmen ist, sondern dass die Verwendung von Matrizen Ihren Code weitaus effizienter machen kann als die Verwendung von Datenrahmen, oftmals erheblich. Dies ist ein Grund, warum intern viele R-Funktionen zu Matrizendaten zwingen, die sich in Datenrahmen befinden.
Datenrahmen sind oft weitaus praktischer. man hat nicht immer nur atomare Datenblöcke herumliegen.
Beachten Sie, dass Sie eine Zeichenmatrix haben können. Sie müssen nicht nur numerische Daten haben, um eine Matrix in R zu erstellen.
Beachten Sie beim Konvertieren eines Datenrahmens in eine Matrix, dass es eine data.matrix()
Funktion gibt, die Faktoren angemessen behandelt, indem sie basierend auf den internen Ebenen in numerische Werte konvertiert werden. Das Erzwingen über as.matrix()
führt zu einer Zeichenmatrix, wenn eine der Faktorbezeichnungen nicht numerisch ist. Vergleichen Sie:
> head(as.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
a B
[1,] "a" "A"
[2,] "b" "B"
[3,] "c" "C"
[4,] "d" "D"
[5,] "e" "E"
[6,] "f" "F"
> head(data.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
a B
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 4 4
[5,] 5 5
[6,] 6 6
Ich verwende fast immer einen Datenrahmen für meine Datenanalyse-Aufgaben, da ich oft mehr als nur numerische Variablen habe. Wenn ich Funktionen für Pakete codiere, zwinge ich fast immer zur Matrix und formatiere die Ergebnisse dann wieder als Datenrahmen. Dies liegt daran, dass Datenrahmen praktisch sind.
@Michal: Matrizen sind nicht wirklich speichereffizienter:
m <- matrix(1:400000, 200000, 2)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 1600776 bytes
... es sei denn, Sie haben eine große Anzahl von Spalten:
m <- matrix(1:400000, 2, 200000)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 22400568 bytes
data.frames
, mehr Flexibilität gegenüber Spaltentypen zu bieten. data.frame(a = rnorm(1e6), b = sample(letters, 1e6, TRUE))
wird matrix
aufgrund von Typenzwang im Speicher viel kleiner sein (6x nach meiner schnellen Berechnung) als die Version.
Die Matrix ist eigentlich ein Vektor mit zusätzlichen Methoden. während data.frame eine Liste ist. Der Unterschied ist auf Vektor gegen Liste zurückzuführen. Halten Sie sich für die Berechnungseffizienz an die Matrix. Verwenden Sie bei Bedarf data.frame.
Matrizen und Datenrahmen sind rechteckige 2D-Arrays und können nach Zeilen und Spalten heterogen sein . Sie teilen einige Methoden und Eigenschaften, aber nicht alle.
Beispiele:
M <- list(3.14,TRUE,5L,c(2,3,5),"dog",1i) # a list
dim(M) <- c(2,3) # set dimensions
print(M) # print result
# [,1] [,2] [,3]
# [1,] 3.14 5 "dog"
# [2,] TRUE Numeric,3 0+1i
DF <- data.frame(M) # a data frame
print(DF) # print result
# X1 X2 X3
# 1 3.14 5 dog
# 2 TRUE 2, 3, 5 0+1i
M <- matrix(c(1,1,1,1,2,3,1,3,6),3) # a numeric matrix
DF <- data.frame(M) # a all numeric data frame
solve(M) # obtains inverse matrix
solve(DF) # obtains inverse matrix
det(M) # obtains determinant
det(DF) # error
Ich kann den Effizienzunterschied zwischen den beiden nicht mehr betonen! Zwar sind DFs in einigen Fällen, insbesondere bei der Datenanalyse, bequemer, sie ermöglichen jedoch auch heterogene Daten, und einige Bibliotheken akzeptieren sie nur. Diese sind jedoch nur zweitrangig, es sei denn, Sie schreiben einen einmaligen Code für eine bestimmte Aufgabe.
Lassen Sie mich Ihnen ein Beispiel geben. Es gab eine Funktion, die den 2D-Pfad der MCMC-Methode berechnen würde. Grundsätzlich bedeutet dies, dass wir einen Anfangspunkt (x, y) nehmen und einen bestimmten Algorithmus iterieren, um bei jedem Schritt einen neuen Punkt (x, y) zu finden, wobei auf diese Weise der gesamte Pfad konstruiert wird. Der Algorithmus beinhaltet die Berechnung einer recht komplexen Funktion und die Erzeugung einer Zufallsvariablen bei jeder Iteration. Wenn er also 12 Sekunden lang ausgeführt wird, dachte ich, dass es in Ordnung ist, wenn man bedenkt, wie viel Zeug er bei jedem Schritt macht. Davon abgesehen sammelte die Funktion alle Punkte im konstruierten Pfad zusammen mit dem Wert einer Zielfunktion in einem 3-Spalten-Datenrahmen. 3 Spalten sind also nicht so groß, und die Anzahl der Schritte war auch mehr als vernünftig 10.000 (bei dieser Art von Problemen sind Pfade mit einer Länge von 1.000.000 typisch, also sind 10.000 nichts). Also dachte ich ein DF 10, 000x3 ist definitiv kein Problem. Der Grund, warum ein DF verwendet wurde, ist einfach. Nach dem Aufruf der Funktion wurde ggplot () aufgerufen, um den resultierenden (x, y) -Pfad zu zeichnen. Und ggplot () akzeptiert keine Matrix.
Dann entschied ich mich irgendwann aus Neugier, die Funktion zu ändern, um den Pfad in einer Matrix zu sammeln. Gerne ist die Syntax von DFs und Matrizen ähnlich. Ich habe lediglich die Zeile, in der df als data.frame angegeben ist, in eine Zeile geändert, die es als Matrix initialisiert. Hier muss ich auch erwähnen, dass der DF im Anfangscode so initialisiert wurde, dass er die endgültige Größe hat. Später im Code der Funktion wurden nur neue Werte in bereits zugewiesenen Leerzeichen aufgezeichnet, und es gab keinen Aufwand für das Hinzufügen neuer Zeilen zum DF. Dies macht den Vergleich noch fairer und vereinfacht auch meine Arbeit, da ich nichts weiter in der Funktion umschreiben musste. Nur eine Zeile ändert sich von der anfänglichen Zuordnung eines Datenrahmens der erforderlichen Größe zu einer Matrix derselben Größe. Um die neue Version der Funktion an ggplot () anzupassen, habe ich die jetzt zurückgegebene Matrix in Daten konvertiert.
Nachdem ich den Code erneut ausgeführt hatte, konnte ich das Ergebnis nicht glauben. Der Code läuft in Sekundenbruchteilen! Anstelle von ca. 12 Sekunden. Und wieder las und schrieb die Funktion während der 10.000 Iterationen nur Werte für bereits zugewiesene Leerzeichen in einem DF (und jetzt in einer Matrix). Und dieser Unterschied gilt auch für die vernünftige (oder eher kleine) Größe 10000x3.
Wenn Ihr einziger Grund für die Verwendung eines DF darin besteht, ihn mit einer Bibliotheksfunktion wie ggplot () kompatibel zu machen, können Sie ihn jederzeit im letzten Moment in einen DF konvertieren - arbeiten Sie mit Matrizen, so weit Sie möchten. Wenn es andererseits einen wesentlicheren Grund für die Verwendung eines DF gibt, z. B. wenn Sie ein Datenanalysepaket verwenden, das ansonsten eine konstante Transformation von Matrizen zu DFs und zurück erfordern würde, oder wenn Sie selbst keine intensiven Berechnungen durchführen und nur Standard verwenden Pakete (viele von ihnen wandeln einen DF tatsächlich intern in eine Matrix um, erledigen ihre Arbeit und wandeln dann das Ergebnis zurück - damit sie alle Effizienzarbeiten für Sie erledigen) oder erledigen einen einmaligen Job, damit Sie sich nicht darum kümmern und sich nicht so fühlen Wenn Sie sich mit DFs wohler fühlen, sollten Sie sich keine Sorgen um die Effizienz machen.
Oder eine andere, praktischere Regel: Wenn Sie eine Frage wie im OP haben, verwenden Sie Matrizen, sodass Sie DFs nur verwenden würden, wenn Sie keine solche Frage haben (weil Sie bereits wissen, dass Sie DFs verwenden müssen, oder weil Sie dies tun nicht wirklich wichtig, da der Code einmalig ist usw.).
Im Allgemeinen sollte dieser Effizienzpunkt jedoch immer im Vordergrund stehen.