rnestedtidyversepurrrr-flextable

How to pass information from one list column to a function applied in another, in a nested data frame


I am working on a report for which I have to export a large number of similar data frames into nice looking tables in Word. My goal is to achieve this in one go, using flextable to generate the tables and purrr / tidyverse to apply all the formatting procedures to all rows in a nested data frame. This is what my data frame looks like:

df <- data.frame(school = c("A", "B", "A", "B", "A", "B"),
            students = c(round(runif(6, 1, 10), 0)),
            grade = c(1, 1, 2, 2, 3, 3))

I want to generate separate tables for all groups in column 'school' and started by using the nest() function within tidyr.

list <- df %>% 
        group_by(school) %>%
        nest()

This gives me a nested data frame to which I can apply the functions in flextable using purrr:

list <- list %>% 
        mutate(ftables = map(data, flextable)) %>%
        mutate(ftables = purrr::map(ftables, ~ set_header_labels(.,
                                               students = "No of students",
                                               grade = "Grade")))

The first mutate generates a new column with flextable objects for each school, and the second mutate applies header labels to the table, based on the column names that are saved in the object.

My goal is now to add another header that is based on the name of the school. This value resides in the list column entitled school, which corresponds row-wise to the tables generated in the list column ftables. How can I pass the name of the school to the add_header function within ftables, using purrr or any other procedure?

Expected output
I have been able to achieve what I want for individual schools with this procedure (identical header cells will later be merged):

school.name <- "A"

ftable.a <- df %>%
            filter(school == "A") %>% 
            select(-school) %>%
            flextable() %>%
            set_header_labels(students = "No of students",
                              grade = "Grade") %>%
            add_header(students = school.name,
                       grade = school.name)

ftable.a

enter image description here


Solution

  • The purrr package provides a function, map2(), that you can use:

    library(flextable)
    library(magrittr)
    library(dplyr)
    library(tidyr)
    library(purrr)
    
    
    df <- data.frame(school = c("A", "B", "A", "B", "A", "B"),
                     students = c(round(runif(6, 1, 10), 0)),
                     grade = c(1, 1, 2, 2, 3, 3))
    byschool <- df %>% 
      group_by(school) %>%
      nest()
    
    byschool <- byschool %>% 
      mutate(ftables = map(data, flextable)) %>%
      mutate(ftables = purrr::map(
        ftables, ~ set_header_labels(.,
                                     students = "No of students",
                                     grade = "Grade"))) %>% 
      mutate(ftables = purrr::map2(ftables, school, function(ft, h){
        add_header(ft, students = h, grade = h)
      } ))