it-swarm.com.de

Soll ich einen Datenrahmen oder eine Matrix verwenden?

Wann sollte man einen data.frame verwenden und wann ist es besser, eine matrix zu verwenden?

Beide enthalten Daten in einem rechteckigen Format, sodass es manchmal unklar ist.

Gibt es allgemeine Faustregeln für die Verwendung des Datentyps?

142
microbe

Ein Teil der Antwort ist bereits in Ihrer Frage enthalten: Sie verwenden Datenrahmen, wenn zu erwarten ist, dass Spalten (Variablen) unterschiedlichen Typs sind (numerisch/Zeichen/logisch usw.). Matrizen sind für Daten des gleichen Typs. 

Daher ist die Auswahlmatrix/data.frame nur dann problematisch, wenn Sie Daten des gleichen Typs haben.

Die Antwort hängt davon ab, was Sie mit den Daten in data.frame/matrix machen. Wenn es an andere Funktionen übergeben wird, bestimmt der erwartete Typ der Argumente dieser Funktionen die Wahl.

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 mit linearer Algebra durchführen möchten.

Datenrahmen sind praktischer, wenn Sie häufig über den Namen (über den compact-Operator $) auf ihre Spalten verweisen.

Datenrahmen sind auch IMHO besser für das Berichten (Drucken) von tabellarischen Informationen, da Sie die Formatierung für jede Spalte separat anwenden können.

170
Michał

Etwas, das nicht von @Michal erwähnt wird, ist, dass nicht nur eine Matrix kleiner als der entsprechende Datenrahmen ist. Durch die Verwendung von Matrizen kann Ihr Code weitaus effizienter sein als die Verwendung von Datenrahmen, oft erheblich. Dies ist ein Grund, warum intern viele R-Funktionen zu Datenmatrizen zwingen, die sich in Datenrahmen befinden.

Datenrahmen sind oft viel bequemer; 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 sie auf der Grundlage der internen Ebenen in numerische Werte konvertieren. Das Zusammenstellen mit 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 programmiere, zwinge ich mich fast immer dazu, die Ergebnisse zu matrizen und dann als Datenrahmen zu formatieren. Dies liegt daran, dass Datenrahmen bequem sind.

72
Gavin Simpson

@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
46
petrelharp

Die Matrix ist eigentlich ein Vektor mit zusätzlichen Methoden. Während data.frame eine Liste ist ..__ Der Unterschied liegt im Vektor-zu-Liste. Für die Berechnungseffizienz bleiben Sie bei der Matrix. Verwenden Sie data.frame, wenn Sie müssen.

9
user8341

Matrizen und Datenrahmen sind rechteckige 2D-Arrays und können .__ sein. heterogen durch Zeilen und Spalten . 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
0
Trisquel

Ich kann den Effizienzunterschied zwischen den beiden nicht mehr betonen! Es ist zwar richtig, dass DFs in bestimmten Fällen der Datenanalyse bequemer sind, sie erlauben jedoch auch heterogene Daten, und einige Bibliotheken akzeptieren sie nur. Diese sind jedoch alles andere als sekundär, 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 berechnet. Im Grunde 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, und so den gesamten Pfad konstruieren. Der Algorithmus beinhaltet das Berechnen einer recht komplexen Funktion und die Erzeugung einiger Zufallsvariablen bei jeder Iteration. Wenn ich also 12 Sekunden lang laufen lasse, dachte ich, dass es gut ist, wenn man bedenkt, wie viel es bei jedem Schritt tut. Davon abgesehen sammelte die Funktion alle Punkte in dem erstellten Pfad zusammen mit dem Wert einer Zielfunktion in einem dreispaltigen Datenrahmen. Also, 3 Spalten sind nicht so groß und die Anzahl der Schritte war auch mehr als vernünftig 10.000 (in dieser Art von Problemen sind Pfade mit einer Länge von 1.000.000 typisch, also sind 10.000 nichts). Also, ich dachte, 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. Zum Glück ist die Syntax von DFs und Matrizen ähnlich. Alles, was ich tat, war, die Zeile, in der df als data.frame angegeben wurde, in eine zu ändern, die es als Matrix initialisiert. Hier muss ich auch erwähnen, dass im ursprünglichen Code DF mit der endgültigen Größe initialisiert wurde, sodass später im Code der Funktion nur neue Werte in bereits zugewiesene Leerzeichen aufgezeichnet wurden und es keinen Zusatzaufwand beim Hinzufügen gab neue Zeilen zum DF. Dies macht den Vergleich noch fairer und auch meine Arbeit einfacher, da ich nichts weiter in die Funktion schreiben musste. Nur eine Zeile wechselt von der anfänglichen Zuweisung eines Datenrahmens der erforderlichen Größe zu einer Matrix derselben Größe. Um die neue Version der Funktion an ggplot () anzupassen, konvertierte ich die jetzt zurückgegebene Matrix in ein data.frame, um sie in ggplot () zu verwenden. 

Nachdem ich den Code erneut ausgeführt hatte, konnte ich das Ergebnis nicht glauben. Der Code läuft im Bruchteil einer Sekunde! Anstelle von etwa 12 Sekunden. Und wieder liest und schreibt die Funktion während der 10.000 Iterationen nur Werte in 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 der einzige Grund, ein DF zu verwenden, die Kompatibilität mit einer Bibliotheksfunktion wie ggplot () ist, können Sie es im letzten Moment immer in ein DF konvertieren - mit Matrizen arbeiten so weit, wie es Ihnen angenehm ist. Wenn andererseits ein grundsätzlicherer Grund für die Verwendung eines DF besteht, z. B. ein Datenanalysepaket, für das ansonsten eine ständige Umwandlung von Matrizen in DF und zurück erforderlich wäre, oder Sie führen selbst keine intensiven Berechnungen durch und verwenden nur den Standard Pakete (viele von ihnen verwandeln intern tatsächlich eine DF in eine Matrix, erledigen ihre Arbeit und wandeln dann das Ergebnis zurück - damit sie alle Effizienz für Sie tun) oder führen Sie eine einmalige Arbeit aus Wenn Sie sich nicht mit DFs beschäftigen und sich wohler fühlen, sollten Sie sich nicht um die Effizienz sorgen. 

Oder eine andere, praktischere Regel: Wenn Sie eine Frage haben, z. B. im OP, verwenden Sie Matrizen. Daher würden Sie DFs nur dann verwenden, 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 immer als Priorität betrachtet werden. 

0
Vadim