R,data.table,非标准评估,错误的输出名称?

时间:2017-09-20 05:19:28

标签: r data.table non-standard-evaluation

首先是我所看到的一个简单例子,然后是一些关于我为什么要做我正在做的事情的背景。

dt = data.table(i=rep(1:3, each=4), t=rep(1:4, times=3), x=runif(12))
dt[, .(sum=sum(x), cnt=.N), keyby=.(i)] # works as expected
#   i      sum cnt
# 1: 1 2.932400   4  
# 2: 2 1.483940   4
# 3: 3 2.113194   4

dt[, .(sum=sum(x), cnt=.N), keyby=list(i)] # same as above

# let j and keyby be specified by user, optionally NULL
j_str = parse(text=".(sum=sum(x), cnt=.N)")
by_str = parse(text="keyby=.(i)")
dt[, eval(j_str), eval(by_str)] # could not find function .
# Error in .(i) : could not find function "."

by_str = parse(text="keyby=list(i)")
dt[, eval(j_str), eval(by_str)] # correct results, but not correct column names
#    keyby      sum cnt
# 1:     1 2.932400   4
# 2:     2 1.483940   4
# 3:     3 2.113194   4

注意两个问题,我最关心的是第二个(错误的列名)。

我特别喜欢做的只是传入一个在data.table []中得到评估的字符串,但我无法让它工作,只有i,j等单独

为什么我这样做,简化版本是我正在编写一个执行此评估的函数。

stupidfnc = function(dt, j_str, by_str) {
    return(dt[, eval(j_str), eval(by_str)])
}

更长的答案是我想循环遍历文件,聚合,rbind,然后再次聚合。但是,聚合数据的完整列表太大而无法容纳在内存中。因此,我正在做一些循环,rbinding,聚合,更多循环,rbinding,聚合,然后聚合聚合,然后循环.....我有一个函数,允许我写一个函数来做到这一点以灵活的方式,无需每次都重写循环。我这样做了很多,并且处理各种循环级别是一个比实际应该更高的认知负担。所以我希望像这样的函数有用。

该功能如下。

#' find z the maximum integer divisor of x st z <= sqrt(x)
#'
#' you can find y = x / z easily enough
#' useful for rbind'ing in chunks w/ a merge or collapse
integer_approx_sqrt = function(x) {
    upper = floor(sqrt(x))
    for (cand in upper:1) {
        if ((x %% cand) == 0) {
            break
        }
    }
    return(cand)
}


#' loop over l, apply FUN, and aggregate with j_aggr by by_agg 
#'
#' todo
mclapply_rbind_aggr = function(l, FUN, j_aggr, by_aggr, mc.cores=1,
                              mc.preschedule=F, chunksize=0, ...) {
    if (chunksize == 0) {
        chunksize = integer_approx_sqrt(length(l))
    }
    if (length(l) <= chunksize | chunksize == 1) {
        dtl = mclapply(l, FUN=FUN, mc.cores=mc.cores,
                       mc.preschedule=mc.preschedule, ...)
    } else {
        dtl = lapply(splitIndices(length(l), chunksize),
               function(indcs) {
                    rbindlist(mclapply(indcs, FUN=FUN, mc.cores=mc.cores,
                             mc.preschedule=mc.preschedule, ...))[,
                     eval(parse(text=j_aggr)), eval(parse(text=by_aggr))]})
    }
    return(rbindlist(dtl)[, eval(parse(text=j_aggr)), eval(parse(text=by_aggr))])
}

0 个答案:

没有答案