Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass strings as code to summarize multiple columns with data.table

Tags:

r

data.table

We would like to summarize a data table to create a lot of new variables that result from the combination of columns names and values from the original data. Here is reproducile example illustrating the result we would like to achieve with two columns only for the sake of brevity

library(data.table)
data('mtcars')
setDT(mtcars)

# Desired output
mtcars[, .(
           acm_hp_carb2 = mean(hp[which( carb <= 2)], na.rm=T),
           acm_wt_am1 = mean(wt[which( am== 1)], na.rm=T)
  ), by= .(cyl, gear)]

Because we want to summarize a lot of columns, we created a function that returns all the strings that we would use to create each summary variable. In this example, we have this:

a <- 'acm_hp_carb2 = mean(hp[which( carb <= 2)], na.rm=T)'
b <- 'acm_wt_am1 = mean(wt[which( am== 1)], na.rm=T)'

And here is our failed attempt. Note that the new columns created do not receive the names we want to assign to them.

mtcars[, .(  
           eval(parse(text=a)),
           eval(parse(text=b))

          ), by= .(cyl, gear)]
like image 432
rafa.pereira Avatar asked Dec 12 '25 14:12

rafa.pereira


1 Answers

Seems like the only part which isn't working is the column names. If you put a and b in a vector and add names to them, you can use lapply to do the eval(parse and keep the names from the vector. I used regex to get the names, but presumably in the real code you can assign the names as whatever variable you're using to construct the strings in the first place.

Result has many NaNs but it matches your desired output.

to_make <- c(a, b)
to_make <- setNames(to_make, sub('^(.*) =.*', '\\1', to_make))

mtcars2[, lapply(to_make, function(x) eval(parse(text = x)))
          , by= .(cyl, gear)]

#    cyl gear acm_hp_carb2 acm_wt_am1
# 1:   6    4          NaN   2.747500
# 2:   4    4         76.0   2.114167
# 3:   6    3        107.5        NaN
# 4:   8    3        162.5        NaN
# 5:   4    3         97.0        NaN
# 6:   4    5        102.0   1.826500
# 7:   8    5          NaN   3.370000
# 8:   6    5          NaN   2.770000
like image 171
IceCreamToucan Avatar answered Dec 15 '25 11:12

IceCreamToucan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!