我有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]])
但我想了解这个错误的原因。感谢
答案 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_name
,as.name(1:5)
评估为`1`
, ...
是唯一的解释。
答案 1 :(得分:0)
更改第二个功能参数,例如
<Bgr, Byte>