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.

InformationsquelleAutor PatrickT | 2015-12-20
Schreibe einen Kommentar