Search code examples
rdplyrpurrrsummarizequasiquotes

Trying to purrr:::map a function across a vector, getting `non-numeric argument` error


I want to map a function to generate summary statistics across a defined vector of columns. When I run the function alone it works fine, but when I map it I'm getting a non-numeric argument to mathematical function error.

Here's the function

sumtab_ce_dt_ow_test <- function (df, depvar, treatvar)
{
  require(dplyr, kableExtra)
  df %>% dplyr::ungroup() %>%
    mutate({{depvar}} := as.numeric({{depvar}})) %>% 
    dplyr::filter(!is.na({{depvar}})) %>%
    group_by({{treatvar}}) %>%
    dplyr::summarize(
      N = n(),
      Med = round(median({{depvar}}, na.rm = T), 2)
    ) %>%
    arrange({{treatvar}})
}

Some sample data:


my_tibble <- tibble(
  rownumber = 1:100,
  a = sample(1:5, 100, replace = TRUE),
  b = sample(1:5, 100, replace = TRUE),
  c = sample(1:5, 100, replace = TRUE),
  phase = sample(c("before", "after"), 100, replace = TRUE),
) %>% 
  mutate(
    across(
      c(a, b, c),
      factor,
      levels = 1:5,
      labels = c("Strongly agree", "Agree", "Neutral", "Disagree", "Strongly disagree")
    )
  )

The simple running of the function works as desired

my_tibble %>% sumtab_ce_dt_ow_test(depvar = a, treatvar = phase)
my_tibble %>% sumtab_ce_dt_ow_test(depvar = b, treatvar = phase)
my_tibble %>% sumtab_ce_dt_ow_test(depvar = c, treatvar = phase)

But when I try to map it I get:

library(rlang)

response_texts <- c("Name 1", "name 2", "blah")
depvars <- c("a", "b", "c")
my_tibble <- my_tibble %>%  mutate(across(all_of(depvars), ~ as.numeric(.x)))

results <- map2_df(depvars, response_texts, function(depvar, response_text) {
  depvar <- enquo(depvar)
  my_tibble %>%
    sumtab_ce_dt_ow_test(depvar = !!depvar, treatvar = phase) %>%
    mutate(response = response_text)
})

This throws

Error in `dplyr::summarize()`:
! Problem while computing `Med = round(median("a", na.rm = T), 2)`.
ℹ The error occurred in group 1: phase = "after".
Caused by error in `round()`:
! non-numeric argument to mathematical function 
Backtrace:
  1. purrr::map2_df(...)
 10. dplyr:::summarise.grouped_df(...)
 11. dplyr:::summarise_cols(.data, dplyr_quosures(...), caller_env = caller_env())
 13. dplyr:::map(quosures, summarise_eval_one, mask = mask)
 14. base::lapply(.x, .f, ...)
 15. dplyr (local) FUN(X[[i]], ...)
 16. mask$eval_all_summarise(quo)
Called from: signal_abort(cnd, .file)
Warning message:
Problem while computing `a = as.numeric("a")`.
ℹ NAs introduced by coercion 

I've tried a few varieties of syntax for this, but I'm always getting this error. I'm sure I'm overlooking something obvious here?


Solution

  • Note that "a" and a are two very different things in R. The first is a character value, the latter is a symbols. Use depvar <- ensym(depvar) to turn your character value into a symbol rather than enquo