Zwei Möglichkeiten zur programmgesteuerten Auswahl von Variablen:
with = FALSE
::
DT = data.table(col1 = 1:3)
colname = "col1"
DT[, colname, with = FALSE]
# col1
# 1: 1
# 2: 2
# 3: 3
..
Präfix 'dot dot' ( ):
DT[, ..colname]
# col1
# 1: 1
# 2: 2
# 3: 3
Weitere Informationen zur..
Notation 'dot dot' ( ) finden Sie unter Neue Funktionen in 1.10.2 (derzeit nicht im Hilfetext beschrieben).
Um Variablen zuzuweisen , setzen Sie die LHS von :=
in Klammern:
DT[, (colname) := 4:6]
# col1
# 1: 4
# 2: 5
# 3: 6
Letzteres wird als Spalten- Plonk bezeichnet , da Sie den gesamten Spaltenvektor durch Referenz ersetzen. Wenn eine Teilmenge i
vorhanden wäre, würde sie durch Referenz untergeordnet. Die Parens (colname)
sind eine Abkürzung, die in Version v1.9.4 auf CRAN Oct 2014 eingeführt wurde. Hier ist die Nachricht :
Die Verwendung with = FALSE
mit :=
ist jetzt in allen Fällen veraltet, da das Umschließen der LHS :=
mit Klammern seit einiger Zeit bevorzugt wird.
colVar = "col1"
DT[, colVar := 1, with = FALSE] # deprecated, still works silently
DT[, (colVar) := 1] # please change to this
DT[, c("col1", "col2") := 1] # no change
DT[, 2:4 := 1] # no change
DT[, c("col1","col2") := list(sum(a), mean(b)] # no change
DT[, `:=`(...), by = ...] # no change
Siehe auch Abschnitt Details in ?`:=`
:
DT[i, (colnamevector) := value]
# [...] The parens are enough to stop the LHS being a symbol
Und um weitere Fragen im Kommentar zu beantworten, gibt es eine Möglichkeit (wie üblich gibt es viele Möglichkeiten):
DT[, colname := cumsum(get(colname)), with = FALSE]
# col1
# 1: 4
# 2: 9
# 3: 15
oder es ist möglicherweise einfacher, nur eval
eine zu lesen, zu schreiben und zu debuggen paste
, ähnlich wie beim Erstellen einer dynamischen SQL-Anweisung, die an einen Server gesendet werden soll:
expr = paste0("DT[,",colname,":=cumsum(",colname,")]")
expr
# [1] "DT[,col1:=cumsum(col1)]"
eval(parse(text=expr))
# col1
# 1: 4
# 2: 13
# 3: 28
Wenn Sie das häufig tun, können Sie eine Hilfsfunktion definieren EVAL
:
EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2))
EVAL("DT[,",colname,":=cumsum(",colname,")]")
# col1
# 1: 4
# 2: 17
# 3: 45
Nun , da data.table
1.8.2 automatisch optimiert j
für Effizienz, kann es vorteilhaft sein , die verwenden eval
Methode. Das get()
In j
verhindert beispielsweise einige Optimierungen.
Oder gibt es set()
. Eine funktionale Form mit geringem Overhead, :=
die hier in Ordnung wäre. Siehe ?set
.
set(DT, j = colname, value = cumsum(DT[[colname]]))
DT
# col1
# 1: 4
# 2: 21
# 3: 66
.
oder..
eine mögliche Maskierung zu vermeiden, fallsDT
dieses Symbol in Zukunft jemals als Spaltenname enthalten sein sollte (und sich an die Konvention zu halten, mit der Spaltennamen nicht beginnen.
). Es gibt einige Feature-Anforderungen, um es robuster zu machen, solche Probleme wie das Hinzufügen von.()
und..()
.fn$
aus dem Paket gsubfn verwenden können, um die Lesbarkeit der EVAL-Lösung zu verbessern :library(gsubfn); fn$EVAL( "DT[,$colname:=cumsum($colname)]" )
.* Dies ist eigentlich keine Antwort, aber ich habe nicht genug Straßenguthaben, um Kommentare zu posten: /
Für jeden, der tatsächlich eine neue Spalte in einer Datentabelle mit einem in einer Variablen gespeicherten Namen erstellen möchte, muss Folgendes funktionieren. Ich habe keine Ahnung, wie es funktioniert. Verbesserungsvorschläge? Ist es sicher anzunehmen, dass eine namenlose neue Spalte immer den Namen V1 erhält?
Beachten Sie, dass ich in der Summe () ganz gut darauf verweisen kann, es aber nicht dazu bringen kann, es im selben Schritt zuzuweisen. Übrigens, der Grund, warum ich dies tun muss, ist, dass colname auf Benutzereingaben in einer Shiny-App basiert.
quelle
V1
es sich um den neuen Namen handelt. Wenn Sie beispielsweise csv mit lesenfread
und eine unbenannte Spalte vorhanden ist, hat diese einenV1
Namen (undread.csv
gibt sie anX
). Es ist also möglich, dass Ihr Tisch bereits einen hatV1
. Vielleicht bekommen Sie einfach den Namen vonnames(DT)[length(names(DT))]
Für mehrere Spalten und eine Funktion, die auf Spaltenwerte angewendet wird.
Wenn Sie die Werte einer Funktion aktualisieren, muss die RHS ein Listenobjekt sein. Wenn Sie also eine Schleife
.SD
mit verwendenlapply
, reicht dies aus.Im folgenden Beispiel werden ganzzahlige Spalten in numerische Spalten konvertiert
quelle
Sie könnten dies versuchen
colname <- as.name ("COL_NAME")
DT2 <- DT [, Liste (COL_SUM = Summe (eval (colname, .SD))), by = c (Gruppe)]
quelle
Abrufen mehrerer Spalten aus data.table über Variable oder Funktion:
was alle ergeben
Ich finde den
.SDcols
Weg am elegantesten.quelle