Daten.Tabelle: warum ist es nicht immer möglich, pass Spaltennamen direkt?
Erste Schritte mit der data.table
- Paket (Autor/maintainer: Matt Dowle). Tolles Paket. Ich Liebe, dass ich schreiben kann dt[, x1]
statt, sagen, dt[, dt$x1]
oder df["x1"]
, für ein Daten.Tabelle dt
eine Spalte name x1
eine Daten.Rahmen df
. Können pass Spaltennamen direkt ist ein attraktives Merkmal der Daten.Tabelle. Aber der Verzicht auf Anführungszeichen um den Namen einer Spalte, (schreiben x1
statt "x1"
) ist nicht immer machbar. Warum?
Programmierung Frage: gibt es irgendwelche Gründe, warum es nicht immer möglich, übergeben Sie den Vektor der Spaltennamen direkt auf eine Daten.Tabelle oder die helper-Funktionen, die das Paket? Zum Beispiel, die subset
, merge
, und melt
Funktionen wurden neu geschrieben, die Daten.Tisch-Paket, aber während subset
verarbeiten kann Spaltennamen direkt merge
und melt
können (siehe unten).
Zu klären, meine Frage ist nicht wenn oder wie aber warum. Es gibt sehr gute Diskussionen mit sehr nützlichen Tipps, z.B. Auswählen /zuweisen von Daten.Tabelle Variablen, die Namen werden gespeichert in einem Vektor-Zeichen und r - übergeben von Variablen Daten.Tabelle Spaltennamen . Mit diesen Antworten und ein bisschen von Versuch und Irrtum, ich bin in der Lage, meinen Weg finden um die quote/unquote Unterscheidungen. Meine Frage ist, warum ist es derzeit nicht möglich, immer verzichtet werden, die Anführungszeichen um Spaltennamen: gibt es ein design, um es? ist es eine vorübergehende situation? sind es die Programmierung Schwierigkeiten?
Unten gebe ich einige Beispiele und die Anzahl der Beispiele für Klarheit.
# load the package
library("data.table") # because I cannot do install.packages(data.table)!!
(i)
# make a data.table
set.seed(1)
dt <- data.table(id = 1:5, x1 = 1:5, x2 = 5:1, x3 = round(runif(5, 1, 5), 0), key = "id")
Kann ich die Daten definieren.Tabelle mit id = 1:10
oder "id" = 1:10
, aber ich muss den Schlüssel definiert werden, mit key = "id"
als key = id
funktioniert nicht:
dt <- data.table(id = 1:5, x1 = 1:5, x2 = 5:1, x3 = round(runif(5, 1, 5), 0), key = id)
##Error in data.table(id = 1:5, x1 = 1:5, x2 = 5:1, x3 = round(runif(5, :
## object 'id' not found
Würden Sie denken zu finden 'id' sollte ziemlich einfach sein für einen Schlüssel, wenn Sie waren auf der Suche für Sie unter dem Spaltennamen? Wäre es programmatisch Klang zu dürfen, fallen die Anführungszeichen auf der RHS der key
?
(ii)
Kann ich subset
mit einem Vektor, der die Spalten oder mit einem Vektor von Spaltennamen:
subset(dt, select = c(x1, x3))
## x1 x3
##1: 1 2
##2: 2 2
##3: 3 3
##4: 4 5
##5: 5 2
subset(dt, select = c("x1", "x3"))
## x1 x3
##1: 1 2
##2: 2 2
##3: 3 3
##4: 4 5
##5: 5 2
Nett und flexibel.
(iii)
Kann ich merge
mit einem Vektor von Spaltennamen:
merge(dt, dt, by = c("x1", "x2"))
## id x1 x2 x3
##1: 1 1 5 2
##2: 2 2 4 2
##3: 3 3 3 3
##4: 4 4 2 5
##5: 5 5 1 2
(dummes Beispiel!) aber nicht mit einem Vektor, der die Spalten:
merge(dt, dt, by = c(x1, x2))
##Error in merge.data.table(dt, dt, by = c(x1, x2)) : object 'x1' not found
Ist es etwas über merge
verhindert, dass es aus der Annahme ein Vektor, der die Spalten den Weg subset
tut?
(iv)
Ebenso melt
nehmen müssen, zitiert die Spaltennamen (oder ganzen zahlen, entsprechend der Spalte Nummern).
Hilfe Beschreibung spezifisch ist, dass melt
akzeptiert "character Vektoren", während die Hilfe für merge
einfach besagt "Vektoren der Spalte "Namen", aber eindeutig mit merge
als mit melt
Zeichen-Vektoren zu erwarten sind.
(v)
Im Fall der j
argument, Zitat von Variablen-Namen ist meist nicht der richtige Ansatz:
# Good:
dt[, .(x1, x2)]
## x1 x2
##1: 1 5
##2: 2 4
##3: 3 3
##4: 4 2
##5: 5 1
# Bad
dt[, .("x1", "x2")]
## V1 V2
##1: x1 x2
# This feature is well documented in the FAQs
# FAQ 2.3: "I'm using c() in the j and getting strange results."
Hinweis für den Leser überhaupt nicht vertraut mit data.tables
dass .()
ist eine Kurzform für list()
und dass dt[, c(x1, x2)]
ist unwahrscheinlich, dass Sie den gewünschten Befehl hier-die j
argument dt[i, j]
sehr viel erwartet eine Liste.
(vi)
Jedoch innerhalb der j
argument dt[i, j]
die LHS des "assignment by reference" Betreiber :=
hat eine verwirrende Konvention.
Wenn die LS eine einzelne Spalte ist, kann es weitergegeben werden, ohne Anführungszeichen. Aber wenn es mehrere Spalten, die Sie übergeben werden müssen als Vektor der zitierten Spaltennamen. Das Handbuch sagt nur "ein Vektor von Spaltennamen", aber Experimente vorschlägt, Sie müssen angegeben werden:
# Good:
dt[, c("x1", "x2") := NULL][]
## id x3
##1: 1 2
##2: 2 2
##3: 3 3
##4: 4 5
##5: 5 2
# Bad:
dt[, c(x1, x2) := NULL]
##Error in eval(expr, envir, enclos) : object 'x1' not found
Die Fehlermeldung ist nicht besonders aufschlussreich. Aber jetzt erinnere ich mich an die FAQ ' s Rat, "Wenn 2 oder mehr Spalten erforderlich sind, verwenden Sie die Liste() oder .() stattdessen." Ich Dummerchen, c(x1, x2)
konnte nicht arbeiten, weil es keine Möglichkeit zu sagen, wo x1
endet und x2
beginnt. Allerdings .(x1, x2)
arbeiten konnte, konnte es nicht?
# Bad:
dt[, .(x1, x2) := NULL]
##Error in eval(expr, envir, enclos) : object 'x1' not found
Nein, alle Dinge betrachtet, die LHS von :=
erwartet einen Vektor der zitiert Spaltennamen. Das Handbuch sollte aktualisiert werden oder, wenn möglich, die data.table
erweitert zu akzeptieren, Listen von nicht börsennotierten Spalten auf der LHS.
Oh wait. Zum löschen mehrerer Spaltennamen, kann ich übergeben eine Liste der zitierten Namen zu LHS? Nein. Listen sind in der Regel wünschenswert, aber nicht auf der LHS von :=
. Die Fehlermeldung ist klar:
# Bad:
dt[, .("x1", "x2") := NULL][]
##Error in `[.data.table`(dt, , `:=`(.("x1", "x2"), NULL)) :
## LHS of := must be a symbol, or an atomic vector (column names or positions).
(vii)
Den i
argument dt[i]
ist zudem so konzipiert, dass nicht börsennotierte Spalten, also "Ausdruck der Spalte Namen"
dt[.(x1, x2)]
## id x1 x2 x3 V2
##1: 1 1 5 2 5
##2: 2 2 4 2 4
##3: 3 3 3 3 3
##4: 4 4 2 5 2
##5: 5 5 1 2 1
Beachten Sie, dass, wenn die Idee war Teilmenge der zwei Spalten x1
und x2
, das sollte getan werden, innerhalb der j
argument, d.h. dt[,.(x1, x2)]
dt[.("x1", "x2")]
##Error in bmerge(i, x, leftcols, rightcols, io, xo, roll, rollends, nomatch, :
## typeof x.id (integer) != typeof i.V1 (character)
dt[c(x1, x2)]
##id x1 x2 x3
## 1: 1 1 5 2
## 2: 2 2 4 2
## 3: 3 3 3 3
## 4: 4 4 2 5
## 5: 5 5 1 2
## 6: 5 5 1 2
## 7: 4 4 2 5
## 8: 3 3 3 3
## 9: 2 2 4 2
##10: 1 1 5 2
dt[c("x1", "x2")]
##Error in bmerge(i, x, leftcols, rightcols, io, xo, roll, rollends, nomatch, :
## typeof x.id (integer) != typeof i.V1 (character)
Ich Sie hier gezeigt haben mehrere Situationen, in denen Spalten, die bestanden werden müssen, als x1
oder als "x1"
und Situationen, in denen beide getan werden kann. Diese Unterschiede können zu Verwirrung führen, um neue Benutzer wie mich. Ich vermute, es gibt mehr als einen Grund für diese beiden Ansätze nebeneinander existieren. Ich würde schätzen, wenn jemand klären könnte, die Sache, für einige meiner Beispiele, wenn nicht für alle von Ihnen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
(i), (iii) und (iv) sound wie Feature-Anforderungen (FRs), siehe hier (also, ja, es ist teilweise aufgrund
data.table
nicht mit volle Reife erreicht).Als auf (v) Sie sagte: "
dt[, c(x1, x2)]
ist unwahrscheinlich, dass Sie den gewünschten Befehl hier", aber in der Tat habe ich gesehen, Situationen, in denen diese Art der Nutzung vonc
innerhalbj
ist, was ich bin nach. Situationen wie (v) sind, was diewith
argument[.data.table
sind.On (vi) und anderswo, die Sie vorschlagen, "Das Handbuch sagt nur 'ein Vektor von Spaltennamen', aber Experimente vorschlägt, Sie müssen angegeben werden"; aber ich denke, das ist eindeutig. Ein Vektor von Spaltennamen bedeutet, dass ein
character
Vektor, derc(x1,x2)
nicht, es sei dennx1
undx2
sind irgendwo definiert alscharacter
Vektoren selbst. Sie können auch hinzufügen einer FR-Dokumentation auf GitHub.Ich bin mir nicht sicher, was Sie nach in (vii), aber in
i
Vektoren der Namen werden verwendet, um Verknüpfungen oder Ausgestanzte Teile (auch eine form der Verknüpfung); siehe vignette auf schnelle subsetting.c(x1, x2)
(wox1
undx2
sind nicht Zeichen-Vektoren), und dass aus diesem Grund der Ausdruck "Zeichen-vector" wurde fürc("x1", "x2")
, aber Sie sagen, dass "Vektor von Spaltennamen" und "character vector" sind Synonyme. Nun sehe ich, dass eine Spalte mit dem Namen ist immer ein Charakter-Vektor, so dass meine interpretation von "Vektor von Spaltennamen" war falsch. Wie nennt man dieses Objektc(x1, x2)
?with
Funktion) wiedata.table
können, so zitiert die Spaltennamen ist die norm, unddata.table
hat einen tollen job gemacht (IMO) zu drängen, hin zu mehr natürlichen syntax, wie Sie ve got in mind. Vielleicht überprüfen Sie heraus einige Hintergrundinformationen zum Lesen auf, wie die Auswertung geschieht in R, vielleicht ein Kapitel in Hadley ' s Buch (1, 2)c(x1, x2)
concatenates die Objektex1
undx2
(so ist es nur ein weiterer Vektor, der Typ, der gleich den meisten-generischer Typx1
undx2
--z.B., wennx1
istnumeric
undx2
integer
,c(x1,x2)
istnumeric
); if ausgewertet, die im Rahmen eines anderen Objekts (list
,data.frame
,data.table
usw.), diese Objekte sind Spaltennamen oder element-Namen; sonst (Vereinfachung ein bisschen), R verwendet, was gefunden wird in der globalen Umgebung. Zeichen (D. H., nicht-alphanumerische Zeichen) sind immer interpretiert als Variablennamen durch R.data.table
, also es kann dauern, etwas übung zu bekommen, wie base-R funktioniert, wenn Sie ' re verwendet, um die Schönheit derdata.table
, die sich selbst ständig zu verbessern.