Home > other >  outputting flextables to .docx in for loop
outputting flextables to .docx in for loop

Time:02-15

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 or 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")
}

CodePudding user response:

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()
}
```


  • Related