简体   繁体   中英

Calculating columns in data.table with variable

I'm trying to calculate columns in a data.table having the calculation passed by variable. The following is the same as what I'm trying to achieve:

dt <- data.table(mpg)
dt[, list(manufacturer, model, mpg_cyl_cty=cty/cyl, mpg_cyl_hwy=hwy/cyl)]

where I want mpg_cyl_cty=cty/cyl, mpg_cyl_hwy=hwy/cyl to come from a variable like:

var <- c('mpg_cyl_cty=cty/cyl', 'mpg_cyl_hwy=hwy/cyl')
dt[, list(manufacturer, model, var)]

I guess there are more problems to this as what type var should be assigned (c or list) and how dt is called, via list or c.

Hope somebody has a suggestion as I'm not finding anything on the WWW.

library(ggplot2)
library(data.table)

dt <- data.table(mpg)
# The original calculation
dt1 <- dt[, list(manufacturer, model, mpg_cyl_cty=cty/cyl, mpg_cyl_hwy=hwy/cyl)]

var <- c('mpg_cyl_cty=cty/cyl', 'mpg_cyl_hwy=hwy/cyl')
# create a string to pass for evaluation
expr <- paste0("`:=`(", paste0(var, collapse = ", "), ")")

dt2 <- dt[, 
          .(manufacturer, model, cty, cyl, hwy)
         ][, eval(parse(text = expr))        # evaluate the expression
         ][, c("cty", "cyl", "hwy") := NULL] # delete unnecessary columns

> print(all.equal(dt1, dt2))
[1] TRUE

Slightly different approach to avoid eval(parse(.)) and operate on language objects.
Instead of c('mpg_cyl_cty=cty/cyl', 'mpg_cyl_hwy=hwy/cyl') it takes just c("cty","hwy") input.

library(data.table)
dt = as.data.table(ggplot2::mpg)
r.expected = dt[, list(manufacturer, model, mpg_cyl_cty=cty/cyl, mpg_cyl_hwy=hwy/cyl)]

cyl.ratio.j = function(var){
    substitute(lhs := rhs, list(
        lhs = as.name(paste0("mpg_cyl_", var)),
        rhs = call("/", as.name(var), as.name("cyl"))
    ))
}

r = dt[, eval(cyl.ratio.j("cty"))
       ][, eval(cyl.ratio.j("hwy"))
         ][, .SD, .SDcols = c("manufacturer", "model", paste0("mpg_cyl_", c("cty","hwy")))]

all.equal(r.expected, r)
#[1] TRUE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM