iacobus iacobus - 3 months ago 14
R Question

pass a character vector as the funs argument for summarize_at

I'm working on a function that takes an argument

funs
that is a string of functions to be applied to a set of variables
vars
. The simplest way to do this seemed to be to use dplyr's
summarize_at
and the SE version of
funs
function.

This works with the functions that are built-in R but doesn't seem to work with user-defined functions. It reports an error that it can't find the user-defined function. However,
summarize_at
works when done "manually."

This function is part of a larger function that produces a box for a Shiny Dashboard. I'd prefer not to have (and have to maintain) a different Shiny module for each type of box (each function and function argument combination).

A minimal reproducible example is below:

# function to compute summary stat
compute_box_value <- function(data, vars, funs) {
f = funs_(funs)
result <- data %>%
summarize_at(.cols = vars, .funs = f)
}

# simple user defined function that gets count of rows with certain values of x
equals <- function(x, test_value) {
sum(x %in% test_value)
}

x <- data.frame(value = sample(1:5, 10, TRUE))

vars <- c("value")

# this works
print(compute_box_value(x, vars, "mean(., na.rm = TRUE)"))

# this works
summarize_at(x, vars, .funs = "equals", test_value = 1)

# this doesn't work (error: couldn't find function equals)
print(compute_box_value(x, vars, "equals(., test_value = 1)"))

Answer

You need to use the formula (~) instead of string:

print(compute_box_value(x, vars, ~equals(., test_value = 1)))

Which gives:

#  value
#1     3

From the documentation:

It’s best to use a formula because a formula captures both the expression to evaluate and the environment where the evaluation occurs. This is important if the expression is a mixture of variables in a data frame and objects in the local environment: