Learn R Programming

flextable (version 0.10.4)

wrap_flextable: Wrap a flextable for use with patchwork

Description

This function wraps a flextable as a patchwork-compliant patch, similar to what patchwork::wrap_table() does for gt tables. It allows flextable objects to be combined with ggplot2 plots in a patchwork layout, with optional alignment of table headers and body with plot panel areas.

Note this is experimental and may change in the future.

Usage

wrap_flextable(
  x,
  panel = c("body", "full", "rows", "cols"),
  space = c("free", "free_x", "free_y", "fixed"),
  n_row_headers = 0L,
  flex_body = FALSE,
  flex_cols = FALSE,
  expand = 0.6,
  just = c("left", "right", "center")
)

Value

A patchwork-compliant object that can be combined with ggplot2 plots using +, |, or / operators.

Arguments

x

A flextable object.

panel

What portion of the table should be aligned with the panel region? "body" means that header and footer will be placed outside the panel region. "full" means that the whole table will be placed inside the panel region. "rows" keeps all rows inside the panel but is otherwise equivalent to "body". "cols" places all columns within the panel region but keeps column headers on top.

space

How should the dimension of the table influence the final composition? "fixed" means that the table width and height will set the dimensions of the area it occupies. "free" means the table dimensions will not influence the sizing. "free_x" and "free_y" allow freeing either direction.

n_row_headers

Number of leading columns to treat as row headers. These columns will be placed outside the panel region and will not participate in alignment with the plot axes.

flex_body

If TRUE, the table body row heights become flexible: the adjacent ggplot determines the panel height and the body rows stretch equally. With panel = "body" or "cols", each row is centered on its category of a discrete y axis (see expand), header and footer keep their fixed size above and below the panel. With panel = "full" or "rows", the whole table fills the panel: body rows take the height left by header and footer and are not aligned with the categories. This is useful to align table rows with discrete bars or categories in a neighbouring plot. Implies free_y for space.

flex_cols

If TRUE, the data column widths (all columns after n_row_headers) become flexible: the adjacent ggplot determines the panel width and the data columns stretch to fill it. Row header columns keep their fixed width. This is useful to align table columns with discrete x-axis categories in a neighbouring plot. Implies free_x for space.

expand

Expansion value matching the ggplot discrete axis expansion (ggplot2::expansion(add = expand)). Default is 0.6, which is the ggplot2 default for discrete axes. Used when flex_body = TRUE (with panel = "body" or "cols") or flex_cols = TRUE. With 0.5, rows (or columns) fill the whole panel.

just

Horizontal alignment of the table within its patchwork panel. One of "left" (default), "right", or "center". Useful when the table is narrower than the available panel width. Ignored when flex_cols = TRUE (columns fill the panel).

Placement and stretching

Two arguments set how the table relates to the panel of the plot (its plotting area, without axes and legends):

  • panel sets where the table is placed: which part of the table is aligned with the panel ("body": the body, header above and footer below; "full": the whole table).

  • flex_body sets whether body rows stretch to fill the panel. With FALSE, rows keep their natural height and the body may be shorter or taller than the plot. With TRUE, the plot sets the height and body rows share it.

To align each row with a category of a discrete y axis, use both panel = "body" and flex_body = TRUE:

flex_body = FALSEflex_body = TRUE
panel = "body"body at the top of the panel, natural height, not alignedrows aligned with the categories
panel = "full"table at the top of the panel, natural heighttable fills the height of the panel, not aligned

The same applies to columns: flex_cols = TRUE with panel = "body" or "cols" aligns data columns with the categories of a discrete x axis.

See Also

Other functions for flextable output and export: df_printer(), flextable_to_rmd(), gen_grob(), htmltools_value(), knit_print.flextable(), plot.flextable(), print.flextable(), repair_docx(), save_as_docx(), save_as_html(), save_as_image(), save_as_pptx(), save_as_rtf(), to_html.flextable()

Examples

Run this code
library(gdtools)
font_set_liberation()
library(ggplot2)
library(patchwork)

set_flextable_defaults(
  font.family = "Liberation Sans",
  font.size = 10,
  big.mark = "",
  border.color = "grey60"
)

# Adapted from 

dataset <- data.frame(
  team = c(
    "FC Bayern Munchen", "SV Werder Bremen", "Borussia Dortmund",
    "VfB Stuttgart", "Borussia M'gladbach", "Hamburger SV",
    "Eintracht Frankfurt", "FC Schalke 04", "1. FC Koln",
    "Bayer 04 Leverkusen"
  ),
  matches = c(2000, 1992, 1924, 1924, 1898, 1866, 1856, 1832, 1754, 1524),
  won     = c(1206,  818,  881,  782,  763,  746,  683,  700,  674,  669),
  lost    = c( 363,  676,  563,  673,  636,  625,  693,  669,  628,  447)
)
dataset$win_pct  <- dataset$won  / dataset$matches * 100
dataset$loss_pct <- dataset$lost / dataset$matches * 100
dataset$team <- factor(dataset$team, levels = rev(dataset$team))

# -- dumbbell chart --
pal <- c(lost = "#EFAC00", won = "#28A87D")
df_long <- reshape(dataset, direction = "long",
  varying = list(c("loss_pct", "win_pct")),
  v.names = "pct", timevar = "type",
  times = c("lost", "won"), idvar = "team"
)

p <- ggplot(df_long, aes(x = pct / 100, y = team)) +
  stat_summary(
    geom = "linerange", fun.min = "min", fun.max = "max",
    linewidth = .7, color = "grey60"
  ) +
  geom_point(aes(fill = type), size = 4, shape = 21,
    stroke = .8, color = "white"
  ) +
  scale_x_continuous(
    labels = scales::percent,
    expand = expansion(add = c(.02, .02))
  ) +
  scale_y_discrete(name = NULL, guide = "none") +
  scale_fill_manual(
    values = pal,
    labels = c(lost = "Lost", won = "Won")
  ) +
  labs(x = NULL, fill = NULL) +
  theme_minimal(base_family = "Liberation Sans", base_size = 10) +
  theme(
    legend.position = "top",
    legend.justification = "left",
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_blank()
  )

# -- flextable --
ft_dat <- dataset[, c("matches", "win_pct", "loss_pct", "team")]
ft_dat$team <- as.character(ft_dat$team)

ft <- flextable(ft_dat)
ft <- border_remove(ft)
ft <- bold(ft, part = "header")
ft <- colformat_double(ft, j = c("win_pct", "loss_pct"),
  digits = 1, suffix = "%"
)
ft <- set_header_labels(ft,
  team = "Team", matches = "GP",
  win_pct = "", loss_pct = ""
)
ft <- color(ft, color = "#28A87D", j = 2)
ft <- color(ft, color = "#EFAC00", j = 3)
ft <- bold(ft, bold = TRUE, j = 2:3)
ft <- italic(ft, italic = TRUE, j = 4)
ft <- align(ft, align = "right", part = "all")
ft <- autofit(ft)

# \dontshow{
cap <- ragg::agg_capture(width = 7, height = 6, units = "in", res = 150)
grDevices::dev.control("enable")
# }
print(
  wrap_flextable(ft, flex_body = TRUE, just = "right") +
    p + plot_layout(widths = c(1.1, 2))
)
# \dontshow{
raster <- cap()
dev.off()
plot(as.raster(raster))
init_flextable_defaults()
# }

Run the code above in your browser using DataLab