data.table:非标准评估的意外错误

时间:2017-04-11 10:23:47

标签: r data.table

我有2个案例要分享:

library(data.table)
dt <- data.table(x = 1:5, y = rep(100, 5))
dt1 <- data.table(col_name = 1:5, y = rep(100, 5))
dt
#   x   y
#1: 1 100
#2: 2 100
#3: 3 100
#4: 4 100
#5: 5 100

dt1
#   col_name   y
#1:        1 100
#2:        2 100
#3:        3 100
#4:        4 100
#5:        5 100


func <- function(data, col_name){
  data[,':='(cum_wt = cumsum(eval(as.name(col_name))))][] # calc the cumulative sum
  return(data)
}

# Case 1 : when the column name is different than function argument
func(dt, "x")
#   x   y cum_wt
#1: 1 100      1
#2: 2 100      3
#3: 3 100      6
#4: 4 100     10
#5: 5 100     15

# Case 2 : when the column name is same as function argument
func(dt1, "col_name")
  

eval(expr,envir,enclos)中的错误:object&#39; 1&#39;找不到

有人可以帮我理解原因吗?以及如何使这个功能适用于这两种情况?

我知道这些的解决方法:比如

data$cum_wt <- cumsum(data[[col_name]])

但我想了解这个错误的原因。感谢

2 个答案:

答案 0 :(得分:2)

您可以尝试替代实施。它使用.SD并将列名作为字符传递给.Sdcols参数。 (也许,这不是最快的方法,但它会返回所需的输出。)

func2 <- function(dat, col_name) {
  checkmate::assert_data_table(dat)
  checkmate::assert_string(col_name)
  checkmate::assert_choice(col_name, names(dat))
  dat[, cum_wt := lapply(.SD, cumsum), .SDcols = col_name] # calc the cumulative sum
  return(dat[])
}

请注意,我已将data重命名为dat,因为data是R函数的名称。

func2(dt, "x")
#   x   y cum_wt
#1: 1 100      1
#2: 2 100      3
#3: 3 100      6
#4: 4 100     10
#5: 5 100     15

func2(dt, "y")
#   x   y cum_wt
#1: 1 100    100
#2: 2 100    200
#3: 3 100    300
#4: 4 100    400
#5: 5 100    500

func2(dt1, "col_name")
#   col_name   y cum_wt
#1:        1 100      1
#2:        2 100      3
#3:        3 100      6
#4:        4 100     10
#5:        5 100     15

OP请求解释错误。所以,我尝试用verbose = TRUE运行OP的原始函数:

func <- function(data, col_name){
  data[,':='(cum_wt = cumsum(eval(as.name(col_name)))), verbose = TRUE][] # calc the cumulative sum
  return(data)
}

func(dt1, "col_name")
  

'(m)得到'在j中找到。 ansvars被设置为所有列。请改用.SDcols或单个j = eval(宏)。两者都将检测所使用的对效率很重要的柱子       旧:col_name,y,cum_wt
      新:col_name,y,cum_wt
       get(col_name)出错:第一个参数无效

不幸的是,这没有更好地了解错误的根本原因,但它表明data.table建议除了使用.SDcols之外的第二种方法:

func3 <- function(data, col_name){
  j_expr <- paste0(":=(cum_wt = cumsum(", col_name, ")")
  data[, j = eval(j_expr), verbose = TRUE][]
  return(data)
}
func3(dt1, "col_name")
#Detected that j uses these columns: <none> 
#   col_name   y cum_wt
#1:        1 100      1
#2:        2 100      3
#3:        3 100      6
#4:        4 100     10
#5:        5 100     15

所以,我认为Frank's comment
首先在表格环境中搜索col_nameas.name(1:5)评估为`1` ...
是唯一的解释。

答案 1 :(得分:0)

更改第二个功能参数,例如

<Bgr, Byte>