rfor-loopr-markdownflextable

Outputting flextables in RMarkdown


I am having trouble outputting formatted flextables to a Word document using RMarkdown.

I have a lot of tables that I need in Word formatting that I am trying to output using a for loop, however they are don't appear when the code is knit.

I've tried a number of combinations using knit_print(), print(), and cat(). Can anyone advise solutions? Example code below.

Dummy Data:

{r message=FALSE, warning=FALSE, include=FALSE}
library(tidyverse)
library(descr)
library(flextable)
library(knitr)

dummy <- data.frame(strat = sample(month.abb[1:4],100, replace = TRUE), 
                    col1 = sample(letters[1:3],100, replace = TRUE), 
                    col2 = sample(letters[5:8],100, replace = TRUE), 
                    col3 = sample(letters[10:3],100, replace = TRUE), 
                    col4 = sample(letters[15:18],100, replace = TRUE))

Table function I am using:

{r message=FALSE, warning=FALSE, include=FALSE}
tbl_func = function(group, variable){
  test <- as.data.frame(table(dummy[[variable]], dummy[[group]])) %>%
    pivot_wider(names_from = Var2, values_from = Freq)
  
  stratnames = names(test)[-1]
  
  test = test %>%
    mutate_if(is.numeric, ~replace(., is.na(.), 0)) %>%
    mutate(across(stratnames, funs(paste0(., " (", round((as.numeric(.)/sum(as.numeric(.)))*100, 1), ")")))) %>%
    select(1, contains("paste0"))

  names(test)[1] <- "strat"

  colnames(test) <-  sub("_paste0", "", colnames(test))
  
  return(test)
}

For Loop:

{r warning=FALSE, results = "asis"}
datalist = list()
for(j in names(dummy)[2:length(names(dummy))]){
  
  for(i in names(dummy)[1]){
    dat <- tbl_func(i, j) %>%
      mutate(var = j)
    
    datalist[[paste0(j,"_",i)]] <- dat
  }
}

tablelist = list()
for(i in seq(from=1, to=length(datalist), by=1)){
  a = i

  dat <- Reduce(function(...) merge(..., by='strat', all.x=TRUE), datalist[a]) %>%
    select(everything())
  
  tablelist[[paste0(datalist[[a]]$var[1], "_frame")]] <- dat
}

for(i in seq(tablelist)){
    knit_print(flextable(tablelist[[i]]) %>%
    theme_box() %>%
    set_table_properties(layout = "autofit") %>%
    font(fontname = "Roboto", part = "all") %>%
    fontsize(size = 8, part = "all") %>%
    merge_h(part = "header") %>% 
    align(align = "center", part = "all") %>%
    align(j = "strat", align = "left", part = "all") %>%
    bg(j = "strat", bg = "#D7D2CB", part = "all") %>% 
    bg(bg = "#BFB6AC", part = "header") %>% 
    color(color = "black", part = "header"))
  
  cat("\n")
}

Solution

  • You need to use flextable_to_rmd().

    ---
    title: "Untitled"
    output: word_document
    ---
    
    ```{r setup, include=FALSE}
    knitr::opts_chunk$set(echo = FALSE)
    library(tidyverse)
    library(descr)
    library(flextable)
    library(knitr)
    
    dummy <- data.frame(strat = sample(month.abb[1:4],100, replace = TRUE), 
                        col1 = sample(letters[1:3],100, replace = TRUE), 
                        col2 = sample(letters[5:8],100, replace = TRUE), 
                        col3 = sample(letters[10:3],100, replace = TRUE), 
                        col4 = sample(letters[15:18],100, replace = TRUE))
    
    tbl_func = function(group, variable){
      test <- as.data.frame(table(dummy[[variable]], dummy[[group]])) %>%
        pivot_wider(names_from = Var2, values_from = Freq)
      
      stratnames = names(test)[-1]
      
      test = test %>%
        mutate_if(is.numeric, ~replace(., is.na(.), 0)) %>%
        mutate(across(stratnames, funs(paste0(., " (", round((as.numeric(.)/sum(as.numeric(.)))*100, 1), ")")))) %>%
        select(1, contains("paste0"))
    
      names(test)[1] <- "strat"
    
      colnames(test) <-  sub("_paste0", "", colnames(test))
      
      return(test)
    }
    ```
    
    
    ```{r warning=FALSE, results = "asis"}
    datalist = list()
    for(j in names(dummy)[2:length(names(dummy))]){
      
      for(i in names(dummy)[1]){
        dat <- tbl_func(i, j) %>%
          mutate(var = j)
        
        datalist[[paste0(j,"_",i)]] <- dat
      }
    }
    
    tablelist = list()
    for(i in seq(from=1, to=length(datalist), by=1)){
      a = i
    
      dat <- Reduce(function(...) merge(..., by='strat', all.x=TRUE), datalist[a]) %>%
        select(everything())
      
      tablelist[[paste0(datalist[[a]]$var[1], "_frame")]] <- dat
    }
    
    for(i in seq(tablelist)){
        flextable(tablelist[[i]]) %>%
        theme_box() %>%
        set_table_properties(layout = "autofit") %>%
        font(fontname = "Roboto", part = "all") %>%
        fontsize(size = 8, part = "all") %>%
        merge_h(part = "header") %>% 
        align(align = "center", part = "all") %>%
        align(j = "strat", align = "left", part = "all") %>%
        bg(j = "strat", bg = "#D7D2CB", part = "all") %>% 
        bg(bg = "#BFB6AC", part = "header") %>% 
        color(color = "black", part = "header") %>% 
        flextable_to_rmd()
    }
    ```