nebulous
nebulous

Reputation: 33

Saving dplyr output from a function to a list

I'm trying to write a function that uses dplyr to summarize counts and percentages for multiple categorical variable, grouped over a single variable.

The function seems to be doing what I want:

#toy dataset
meals <- data.frame(
  day = rep(1:6, each = 2),
  parent = rep(c("mom", "dad"), 6),
  breakfast = sample(c("cereal", "banana", "yogurt"), size = 12, replace = TRUE), 
  lunch = sample(c("sandwich", "soup"), size = 12, replace = TRUE)
)

#function to print summary tables - works
summarytable <- function(data, dep, ind) {
  for (var in ind) {
    
    x <- data %>%
      group_by({{dep}}) %>% 
      count(.data[[var]] ) %>% 
      mutate(pct = n/sum(n), total = paste0(n, " (", pct, ")")) %>% 
      select(-n, -pct) %>% 
      pivot_wider(names_from = {{dep}}, values_from = total)
    
    print(x)
  }
}

meals %>%  summarytable(dep = parent, ind = c("breakfast", "lunch"))
# A tibble: 3 x 3
  breakfast dad                   mom                  
  <fct>     <chr>                 <chr>                
1 banana    3 (0.5)               2 (0.333333333333333)
2 cereal    2 (0.333333333333333) 1 (0.166666666666667)
3 yogurt    1 (0.166666666666667) 3 (0.5)              
# A tibble: 2 x 3
  lunch    dad                   mom                  
  <fct>    <chr>                 <chr>                
1 sandwich 4 (0.666666666666667) 2 (0.333333333333333)
2 soup     2 (0.333333333333333) 4 (0.666666666666667)

But when I try to save the tables in a list, it doesn't seem to be working.

#function to save output in a list - not working
summarytable2 <- function(data, dep, ind) {
  for (var in ind) {
    
    x <- data %>%
      group_by({{dep}}) %>% 
      count(.data[[var]] ) %>% 
      mutate(pct = n/sum(n), total = paste0(n, " (", pct, ")")) %>% 
      select(-n, -pct) %>% 
      pivot_wider(names_from = {{dep}}, values_from = total)
    
    outList[[var]] <- x
  }
}

outList <- list()
meals %>%  summarytable2(dep = parent, ind = c("breakfast", "lunch"))
outList
list()

I tried pre-specifying the number of elements in outList as suggested here and adding an iterator (here), but still no luck.

Any suggestions would be greatly appreciated!

Upvotes: 1

Views: 438

Answers (1)

akrun
akrun

Reputation: 887951

We can create the outList within the function and return that as output

library(dplyr)
library(formattable)
summarytable2 <- function(data, dep, ind) {
  outList <- vector('list', length(ind))
  names(outList) <- ind
  for (var in ind) {
    
    x <- data %>%
      group_by({{dep}}) %>% 
      count(.data[[var]] ) %>% 
      mutate(pct = percent(n/sum(n), 1), total = paste0(n, " (", pct, ")")) %>% 
      select(-n, -pct) %>% 
      pivot_wider(names_from = {{dep}}, values_from = total)
    
    outList[[var]] <- x
  }
  return(outList)
}

-checking

summarytable2(meals, dep = parent, ind = c("breakfast", "lunch"))
#$breakfast
# A tibble: 3 x 3
#  breakfast dad       mom      
#  <chr>     <chr>     <chr>    
#1 banana    1 (16.7%) 3 (50.0%)
#2 cereal    2 (33.3%) 2 (33.3%)
#3 yogurt    3 (50.0%) 1 (16.7%)

#$lunch
# A tibble: 2 x 3
#  lunch    dad       mom      
#  <chr>    <chr>     <chr>    
#1 sandwich 1 (16.7%) 3 (50.0%)
#2 soup     5 (83.3%) 3 (50.0%)

Upvotes: 2

Related Questions