how to use a named variable within a function in r

by Jose   Last Updated June 29, 2018 00:26 AM

Assume the following dummy data frame:

dt <- data.table(A=c("a", "a", "a", "b", "b", "b", "c", "c", "c", "d", "d", "d"), 
             B=c("e", "e", "e", "e", "e", "e", "f", "f", "f", "f", "f", "f"), 
             C=1:12, 
             D=13:24)

I'd like to calculate some stadistics (say, mean and standard deviation) per each numeric column ("C" and "D") and each time grouped by the factor columns c("A"), c("B"), and c("A", "B). In the actual data frame, I have about 40 numeric columns, 10 factor columns that group in different combinations and a large list of statistics I'd like to calculate. Based on the answer (by @thelatemail) I got from a previous question, I know I can use the code below to deal with factor groupings (by=) using a list:

groupList <- list(c("A", "B"), c("A"), c("B"))
out <- vector("list", 3)
out <- lapply(
  groupList,
  function(x) {
    dt[, .(mean=mean(C), sd=sd(C)), by=x]
  }
)

Now I'd like to go a step further and create a variable containing a list of the names of numeric columns in the data frame and use the name of that variable within the function above. I came out with the following code but unfortunately, it doesn't work. My idea is to use a loop to extract a value from measureList at each turn and place that value within the mean, sd functions. Any ideas? The loop is how I tend to think of these things but I'll be glad to get rid of it if it makes the code faster or more efficient (particularly because one of the factor columns I have has 90 levels). I'd appreciate any pointer to solve this problem! Thanks.

factorList <- list(c("A"), c("B"), c("A", "B"))
measureList <- list(c("C"), c("D"))

out <- vector("list", 2)
for(i in 1:length(measureList)){
  out[[i]] <-lapply(
    factorList,
    function(x) {
      dt[, .(mean=mean(eval(measureList[[i]])), 
             sd=sd(eval(measureList[[i]]))),
         by = x]
    }
  )
}


Answers 2


This uses dplyr and purrr, but I think it works.

library(dplyr)
library(purrr)

combos <- expand.grid(factorList, measureList)
map2(combos[, 1],
     combos[, 2],
     ~ dt %>% group_by_at(.x) %>% summarize_at(.y, funs(mean, sd)))
zack
zack
June 28, 2018 22:51 PM

You can use outer with a vectorized function or use Map as shown below:

m = function(x,y)dt[, .(mean=mean(get(y)), sd=sd(get(y))), by=x]

c(outer(factorList,measureList,Vectorize(m)))

or

Map(m,rep(factorList,each=length(measureList)),measureList)
Onyambu
Onyambu
June 29, 2018 00:24 AM

Related Questions


looping over different factor levels in a dataframe

Updated December 08, 2017 01:26 AM

Cleaning data in R using for loops

Updated May 23, 2020 00:26 AM

Selective elimination from a list in R

Updated January 29, 2019 01:26 AM