beide Spaltennamen und den Zielwert innerhalb 'J' Ausdruck Auswertung innerhalb `data.table`
Betrachtentarget <- "vs"
value <- 1
library(data.table)
dt <- as.data.table(head(mtcars))
Also innerhalb Ich versuche, beide Spaltennamen übergeben und einen Wert als Variablen in den j
Ausdruck data.table
Umgebung, etwas, das entspricht
dt[, vs == 1]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
wäre, wenn nur der Wert der Variable, es schön
dt[, vs == value]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
arbeitet
Wir können auch die Spalte im data.table Umfang nennen, wenn es
dt[, target, with = FALSE]
# vs
# 1: 0
# 2: 0
# 3: 1
# 4: 1
# 5: 0
# 6: 1
eine Variable ist Aber ich kann nicht verstehen, wie die beiden auf einfache Weise
Hinweis kombinieren: ich bin mir bewusst, dass ich einfach tun:
dt[[target]] == value
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
Aber ich brauche es in der Datentabelle Umfang so dass ich andere Spalten von r ändern könnte bersicht, so etwas wie
dt[, NEWCOL := sum(vs == 1), by = am]
hier So sind meine Versuche, wenn beide Spaltenname und der Wert sind Variablen
dt[, target == value, with = FALSE]
# Null data.table (0 rows and 0 cols)
dt[, target == value]
# [1] FALSE
dt[, (target) == value]
# [1] FALSE
dt[, .(target == value)]
# V1
# 1: FALSE
dt[, eval(target) == value]
# [1] FALSE
dt[target %in% value]
## Empty data.table (0 rows) of 11 cols: mpg,cyl,disp,hp,drat,wt...
Schließlich kam ich mit
dt[, .SD[[target]] == value]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
aber es ist sehr ineffizient, Hier ist ein einfacher Benchmark
set.seed(123)
n <- 1e6
dt <- data.table(vs = sample(1L:30L, n, replace = TRUE), am = seq_len(n))
system.time(dt[, NEWCOL := sum(.SD[[target]] == value), by = am])
# user system elapsed
# 13.00 0.02 13.12
system.time(dt[, NEWCOL2 := sum(vs == value), by = am])
# user system elapsed
# 0.82 0.00 0.83
Frage: Gibt es einen besseren Weg, dies zu tun, dass ich hier vermisse? Etwas entweder mehr idiomatische oder wesentlich effizienter
bearbeiten
Ursprünglich ich war auf der Suche nach etwas, idiomatisch, so dachte ich @GGrothendieck einfache Lösung mit get
war derjenige, aber überraschend alle @ Richard Version sind auch die Version zu schlagen, dass ins't jede Bewertung des Spaltennamen tut
set.seed(123)
n <- 1e7
dt <- data.table(vs = sample(1L:30L, n, replace = TRUE), am = seq_len(n))
cl <- substitute(
x == y,
list(x = as.name(target), y = value)
)
cl2 <- call("==", as.name(target), value)
system.time(dt[, NEWCOL := sum(vs == value), by = am])
# user system elapsed
# 0.83 0.00 0.82
system.time(dt[, NEWCOL1 := sum(.SD[[target]] == value), by = am])
# user system elapsed
# 8.97 0.00 8.97
system.time(dt[, NEWCOL2 := sum(get(target) == value), by = am])
# user system elapsed
# 2.35 0.00 2.37
system.time(dt[, NEWCOL3 := sum(eval(cl)), by = am])
# user system elapsed
# 0.69 0.02 0.71
system.time(dt[, NEWCOL4 := sum(eval(cl2)), by = am])
# user system elapsed
# 0.76 0.00 0.77
system.time(dt[, NEWCOL5 := sum(eval(as.name(target)) == value), by = am])
# user system elapsed
# 0.78 0.00 0.78
Probieren Sie 'get (target) ' –
Das sehen alle wirklich komisch aus. (@ jangoreckis Bounty hat mich hierher gebracht.) Warum benutzt man 'by' mit einem Zeilenzähler? Das kann unmöglich optimal sein. Und warum 'sum' einen 0/1-Skalar? Derselbe Vektor kann 700x schneller (auf meinem Computer) mit 'dt [, mycol: = 0L]; dt [get (target) == value, mycol: = 1L]' erzeugt werden. Prüfe mit 'dt [, table (mycol, NEWCOL5)]' – Frank
Außerdem habe ich eine interessante Ersetzung von Richards Antwort erfahren. Ich kann immer noch nicht mit ähnlicher * Programmieraktualisierung durch Referenz * auf Zeichenvektoreingabe umgehen. Etwas wie: a) 'select <- c (" value "); DT [JN, c ("Wert"): = list (i.value)] 'und b)' select <- c ("value", "meta"); DT [JN, c ("Wert", "Meta"): = Liste (i.value, i.meta) '. Versucht mit 'lapply (select, as.name (paste0 (" i. ", Select))) aber' names 'nested in Liste scheint nicht eingefangen zu sein. Ich könnte dafür eine neue Frage stellen. – jangorecki