Misha
Misha

Reputation: 3126

table generation in rmarkdown using gtsummary and flextable

Most collaborators prefer tables in word format. With the advent of rmarkdown,knitr,gtsummary and flextable this is finally coming of age, but I cannot wrap my head around how I can generate the final table below without resorting to manually setting the indentation. I think table I below leaves far too much air between the rows, but I cannot figure out how to set the row spacing tighter programmatically (tried autofit, height, height_all, hrule without obtaining desired output). Instead, I used the compact style in word to generate tbl 2 below. However, then I´d have to manually insert the indentation for the cyl categories. Anyone know how this can be done programmatically?


title: "testing T´s"
output:
  word_document:
    reference_docx: temp.docx
  html_document:
    df_print: paged
editor_options:
  chunk_output_type: inline
---

Plain 
====
```{r results='asis',echo=FALSE,message=FALSE}
library(gtsummary)
library(flextable)
set_gtsummary_theme(theme_gtsummary_jama())
a <- mtcars[1:20,c(1,2,9,4)] 
  b <- tbl_summary(a,
    missing="ifany",
    by=am,
    type=list(cyl~"categorical"))%>% 
      bold_labels() %>%
  add_p() %>% add_overall()
```


Flextable
====
```{r results='asis',echo=FALSE,message=FALSE}
fl <- gtsummary::as_flextable(b) %>%  font(fontname = "Bodoni 72",part = "all") %>% fontsize(size=8,part="all") %>%  autofit(add_h = -.5) 
fl
```

enter image description here

Upvotes: 3

Views: 2005

Answers (1)

Daniel D. Sjoberg
Daniel D. Sjoberg

Reputation: 11680

At the moment, there is no simple way to do this. But I have included a code example that I think does solve your problem.

With {flextable} it's important the order the functions are called. Running as_flextable() then appending additional calls doesn't seem to get you what you want.

The alternative is save the calls, insert the new flextable function calls where needed, then evaluate the calls. That is what is done in the example below.

---
title: "Untitled"
output: word_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE)
```


```{r}
library(tidyverse)
library(gtsummary)
library(flextable)

set_gtsummary_theme(theme_gtsummary_jama())

tbl <- 
  mtcars[1:20, c(1, 2, 9, 4)] %>%
  tbl_summary(
    missing = "ifany",
    by = am,
    type = list(cyl ~ "categorical")
  ) %>%
  bold_labels() %>%
  add_p() %>%
  add_overall()
```


### Default Flextable

```{r}
gtsummary::as_flextable(tbl)
```

### Compact Flextable

```{r}
# this function inserts additional flextable calls, then evaluates the calls
update_flextable_calls <- function(x, call_list, after) {
  # saving calls that create the flextable
  x_calls <- gtsummary::as_flextable(x, return_calls = TRUE)

  # adding new calls at `after=`
  after_n <- names(x_calls) %in% after %>% which()
  x_calls <- c(
    x_calls[1:after_n],
    call_list,
    x_calls[(after_n + 1):length(x_calls)]
  )

  # evaluating calls
  x_calls %>%
    unlist() %>%
    purrr::compact() %>%
    # concatenating expressions with %>% between each of them
    purrr::reduce(function(x, y) rlang::expr(!!x %>% !!y)) %>%
    # evaluating expressions
    eval()
}

# list of calls that make a table compact
compact_calls <- list(
  rlang::expr(font(fontname = "Bodoni 72", part = "all")),
  rlang::expr(fontsize(size = 8, part = "all")),
  rlang::expr(padding(padding.top = 0, part = "all")),
  rlang::expr(padding(padding.bottom = 0, part = "all"))
)

# adding the compact calls, and evaluating them
update_flextable_calls(
  x = tbl, # gtsummary table
  call_list = compact_calls, # calls that make flextable compact
  after = "footnote" # add calls after the "footnote" functions
) 
```

enter image description here

This obviously isn't a great permanent solution. We have a theme called theme_gtsummary_compact() that makes the {gt} tables compact with smaller font and reduced padding. We can update the theme to also make flextables more compact! I'd love it if you created an issue on GitHub to update theme_gtsummary_compact() for flexables, and we can collaborate on a solution that works well for you. https://github.com/ddsjoberg/gtsummary/issues/new/choose

Upvotes: 4

Related Questions