考慮評估都列名和內內``j`表達目標值data.table`
target <- "vs"
value <- 1
library(data.table)
dt <- as.data.table(head(mtcars))
所以我想通過這兩個列名和內的值作爲變量進入j
表達data.table
環境,東西就相當於
dt[, vs == 1]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
如果只值的變量,它工作得很好
dt[, vs == value]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
我們也可以撥打data.table範圍內的列時,它是一個變量
dt[, target, with = FALSE]
# vs
# 1: 0
# 2: 0
# 3: 1
# 4: 1
# 5: 0
# 6: 1
但我找不出如何兩個簡單的方式
注意結合:我很清楚,我可以簡單地做:
dt[[target]] == value
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
但我需要它的數據表範圍之內,所以我可以修改由R等欄目eference,像
dt[, NEWCOL := sum(vs == 1), by = am]
因此,這裏是我的嘗試時,都列名和值是變量
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...
最後我想出了
dt[, .SD[[target]] == value]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
,但它是非常低效的,這裏有一個簡單的基準
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
問題:有沒有更好的方法來做到這一點,我在這裏失蹤?無論是東西更地道或更有效
編輯
本來我一直在尋找一些成語,所以我想用get
@GGrothendieck簡單的解決方案是一個,但令人驚訝的所有@Richard版本是甚至超過了該版本ins't做列名的任何評價
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
試試'get(target)' –
這些都讓我看起來很奇怪。 (@ jangorecki的賞金把我帶到了這裏。)爲什麼在行計數器上使用'by'?這不可能是最佳的。爲什麼'總和'一個0/1標量?使用'dt [,mycol:= 0L]; dt [獲取(目標)==值,mycol:= 1L]',可以將相同的矢量快700倍(在我的計算機上)。用'dt [,table(mycol,NEWCOL5)]檢查' – Frank
除了我從Richard的回答中學到了有趣的替換之外,我仍然無法在字符向量輸入中處理類似*通過引用*編程更新。例如:a)'select < - c(「value」); DT [JN,c(「value」):= list(i.value)]'和b)'select < - c(「value」,「meta」); DT [JN,c(「value」,「meta」):= list(i.value,i.meta)'。試着用lapply(select,as.name(paste0(「i。」,select)))'但嵌套在列表中的'name'似乎沒有被捕獲。我可能會爲此提出一個新問題。 – jangorecki