select/分配给data.tablevariables名称存储在一个字符向量中

如果variables名存储在字符向量中,如何引用data.table的variables? 例如,这适用于data.frame

 df <- data.frame(col1 = 1:3) colname <- "col1" df[colname] <- 4:6 df # col1 # 1 4 # 2 5 # 3 6 

我怎样才能执行相同的操作data.table,无论有或没有:=符号? dt[ , list(colname)]的显而易见的东西不起作用(我也没有期望它)。

试试:

 DT = data.table(col1 = 1:3) colname = "col1" DT[, colname, with = FALSE] # select # col1 # 1: 1 # 2: 2 # 3: 3 DT[, (colname) := 4:6] # assign # col1 # 1: 4 # 2: 5 # 3: 6 

后者被称为列plonk ,因为您通过引用来replace整个列向量。 如果i存在的子集,它将通过引用进行分配。 在CRAN 2014年10月的版本v1.9.4中,引人入胜(colname)是速记。这里是新闻项目:

 Using `with = FALSE` with `:=` is now deprecated in all cases, given that wrapping the LHS of `:=` with parentheses has been preferred for some time. 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 

参见?`:=` 细节部分:

 DT[i, (colnamevector) := value] # [...] The parens are enough to stop the LHS being a symbol 

并回答进一步的问题,这里有一个方法(和往常一样有很多方法):

 DT[, colname := cumsum(get(colname)), with = FALSE] # col1 # 1: 4 # 2: 9 # 3: 15 

或者,您可能会发现仅仅为了eval一个paste而读取,写入和debugging更容易,类似于构造一个dynamicSQL语句以发送到服务器:

 expr = paste0("DT[,",colname,":=cumsum(",colname,")]") expr # [1] "DT[,col1:=cumsum(col1)]" eval(parse(text=expr)) # col1 # 1: 4 # 2: 13 # 3: 28 

如果你做了很多,你可以定义一个辅助函数EVAL

 EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2)) EVAL("DT[,",colname,":=cumsum(",colname,")]") # col1 # 1: 4 # 2: 17 # 3: 45 

现在data.table 1.8.2自动优化j效率,最好使用eval方法。 例如, jget()可以防止一些优化。

或者,有set() 。 一个低开销,函数forms:= ,在这里就可以了。 看到?set

 set(DT, j = colname, value = cumsum(DT[[colname]])) DT # col1 # 1: 4 # 2: 21 # 3: 66 

*这真的不是一个答案,但我没有足够的街道信誉发表评论:/

无论如何,对于任何人可能正在寻找实际上创build一个名称存储在一个variables的数据表中的新列,我有以下工作。 我不知道它的performance。 任何改善build议? 假定一个无名的新列总是被赋予名称V1是否安全?

 colname <- as.name("users") # Google Analytics query is run with chosen metric and resulting data is assigned to DT DT2 <- DT[, sum(eval(colname, .SD)), by = country] setnames(DT2, "V1", as.character(colname)) 

注意我可以在sum()中引用它,但似乎无法让它在同一步中分配。 顺便说一句,我需要这样做的原因是colname将基于Shiny应用程序中的用户input。

用于列值的多列和一个函数。

当从一个函数更新值时,RHS必须是一个列表对象,所以用.SDlapply上使用一个循环就可以了。

下面的例子将整数列转换为数字列

 a1 <- data.table(a=1:5, b=6:10, c1=letters[1:5]) sapply(a1, class) # show classes of columns # ab c1 # "integer" "integer" "character" # column name character vector nm <- c("a", "b") # Convert columns a and b to numeric type a1[, j = (nm) := lapply(.SD, as.numeric ), .SDcols = nm ] sapply(a1, class) # ab c1 # "numeric" "numeric" "character"