+ - 0:00:00
Notes for current slide
Notes for next slide

Why R? Webinar 037

Tabular reporting with the flextable package

David Gohel

2021-03-11

1 / 39

About me

Me and my family

Some of my open source

Funder of

Based in Paris, France

at https://www.ardata.fr

With Clémentine and Panagiotis

package development, deploiement, support, migration, shiny development

scientific cloud computing environment (jupyterhub, RStudio, ...)

R Trainings

2 / 39

Short introduction to

3 / 39

Why flextable?

  • Tables, just like graphs, can be a very good way to provide synthetic and clear information.

  • They are easy to read by our public.

  • They must be easy to produce from R.

  • My customers always ask for nice tables, in Word, PowerPoint or HTML (not so much for PDF).

4 / 39

Package overview

1 - Extensive formatting capabilities

The package offers a flexible and rich syntax allowing:

  • merging cells,
  • add header lines,
  • change formats,
  • modify the display of the data in the table .

plus mix text, images, ggplot, hyperlinks

2 - Publication-Quality

Support for caption and cross-references in HTML, Word and PDF

Everything can be coded, no "copy paste your table"

Already used by CRO, pharmaceutical companies, public health institutes, ...

3 - Static tables

A flextable is a static table that shows the data contained in a data.frame,

or that shows a view of data transformed by as_flextable.

4 - Supported outputs

+ support for png output via webshot

5 - Documentation

A detailed documentation with many illustrations is available, made with

5 / 39

History

  • 2017-03-28: first realease on CRAN, support officer and HTML R Markdown. Idea was to replace ReporteRs::FlexTable.
  • 2017-10-30: Merge pull request #37 from mnazarov/master. Added functionality to insert flextable's in R Markdown for docx output.
  • 2017-11-22: R Markdown support for pptx output.
  • 2019-01-29: Refactor internals and add flextable::compose (for complex formatting)

6 / 39

A first example

flextable(airquality[ sample.int(5),]) %>%
add_header_row(colwidths = c(4, 2), values = c("Air quality", "Time")) %>%
theme_vanilla() %>%
add_footer_lines("Daily measurements in New York, May to September 1973.") %>%
color(part = "footer", color = "#666666") %>%
set_caption(caption = "New York Air Quality Measurements")

New York Air Quality Measurements

7 / 39

Principles

8 / 39

Parts of a flextable

A flextable is composed of 3 parts:

header: by default, there is only one line containing the names of the data.frame columns.

body: contains the data from the data.frame.

footer: by default, this part is not available, but it may contain footnotes and any other content.

part=all <==> header + body + footer

9 / 39

Columns to display

  • The col_keys argument of the flextable function allows to select the columns of the data.frame to be displayed.
  • The other columns can however be used later.
  • If a column is filled in the argument but does not exist, an empty column will be created.
dat <- head(airquality, n = 3)
flextable(dat)

flextable(data = dat,
col_keys = c("Ozone", "Temp",
"Month", "Day"))

flextable(data = dat,
col_keys = c("Month", "Day",
"dummy", "Ozone"))

10 / 39

Selectors

Selectors let you select rows and or columns where operations will be applied.

They are available to format (change color, background color, borders), define the content of the cells, merge cells, ...

The i selector corresponds to the rows and the j selector corresponds to the columns. They can be expressed in different ways:

  • as a formula: i = ~ col %in% "xxx", j = ~ col1 + col2.
  • as a character vector: j = c("x", "y").
  • as an integer vector: i = 1:3, j = 1:3.
  • as a logical vector: i = c(TRUE, FALSE), j = c(TRUE, FALSE).
ft <- flextable(dat)
ft %>%
color(
i = ~ Ozone < 40,
j = c("Ozone", "Solar.R"),
color = "orange")

11 / 39

Cell content

By default, the cells of the flextable are filled with the content of the data.frame cells.

ft <- flextable(dat)
ft

ft <- colformat_double(ft, digits = 2) %>%
colformat_int(prefix = "#")
ft

You can change the displayed content of a cell with the following functions :

  • colformat_double, to define how to display double columns,
  • colformat_int, to define how to display int columns,
  • colformat_char, to define how to display character columns,
  • colformat_datetime() & colformat_date(),
  • colformat_image(),
  • colformat_lgl(),
  • colformat_num()
12 / 39

Cell with multi-content

The cells of the flextable are filled with more than a content.

ft <- flextable(dat,
col_keys = c("Month", "Day", "Solar.R"))
ft <- compose(ft,
j = "Solar.R",
value = as_paragraph(
Solar.R, " (", as_b(Ozone), ")"
)
)
ft

ft <- compose(ft,
j = "Solar.R", i = 1, part = "header",
value = as_paragraph(
as_i("Solar"), " ",
colorize(as_sup("R"), "red"))
)
ft

13 / 39

As flextable

Function as_flextable is a generic function to cast objects into flextable.

So far, this method exist for objects lm, glm, mgcv::gam, xtable, htest, as_grouped_data.

dat <- attitude
dat$high.rating <- (dat$rating > 70)
probit.model <- glm(high.rating ~ learning + critical +
advance, data=dat, family = binomial(link = "probit"))
ft <- as_flextable(probit.model)
ft

14 / 39

Header and footers

15 / 39

Header labels

This is the bottom row of the header part (or the only row by default).

ft <- flextable(head(airquality),
col_keys = c("Month", "Day", "Solar.R")) %>%
set_header_labels(Solar.R = "Solar R (lang)")
ft

16 / 39

Set default values to ease your work

The default formatting properties (see get_flextable_defaults()) are automatically applied to every flextable you produce. Use set_flextable_defaults() to override them. Use init_flextable_defaults() to re-init all values with the package defaults.

set_flextable_defaults(font.size = 10,
padding = 5,
font.family = "Arial",
na_str = "",
# eastasia.family =
post_process_html = function(x){
x <- theme_booktabs(x)
autofit(x, part = "body")
})
ft <- flextable(head(airquality),
col_keys = c("Month", "Day", "Solar.R")) %>%
set_header_labels(
Solar.R = "Solar R (lang)")

17 / 39

Add more rows

To add lines to a flextable, the add_header_row and add_footer_row functions are available. The colwidths argument will indicate the number of columns for each new cell being added.

ft <- flextable(head(airquality))
ft <- add_header_row(
x = ft,
values = c("measurements", "time"),
colwidths = c(4, 2))

18 / 39

Sugar function: add lines

The functions add_header_lines and add_footer_lines allow you to add rows to the table at the header or at the end of the table, these rows will contain only one single cell.

ft <- add_header_lines(ft,
values = c(
"this is a first line",
"this is a second line"
)
)

19 / 39

Walkthrough with Mario Kart characters

20 / 39

Hidden statistics of Mario Kart characters?

In Mario Kart 8 Deluxe on Switch, each character has its own set of statistics, but unlike karts and customization elements, they are not displayed directly on the screen.

Characters all have their own very precise statistics: speed (different according to the environment), maneuverability, power of mini-turbos, absolute speed, ...

These parameters are rated out of 6 and have been listed by the community of fans of the game.

We will use flextable to present the detail of these statistics by characters.

Data are available here: https://docs.google.com/spreadsheets/d/1g7A-38tn9UAIbB2B3sZI-MpILsS3ZS870UTVMRRxh4Q/edit#gid=0

21 / 39

Expected result

22 / 39

The flextable code

Open codes/mario.R

23 / 39

Adding to a document

24 / 39

With officer technology

Inserting a flextable in a document can be done in different ways:

  • For Word, use flextable::body_add_flextable() function.

  • For PowerPoint, use officer::ph_with() function.

read_docx() %>%
body_add_flextable(ft) %>%
print(target = "reports/mario-officer.docx")
read_pptx() %>%
add_slide() %>%
ph_with(ft, location = ph_location_type()) %>%
print(target = "reports/mario-officer.pptx")
25 / 39

Easy exportation

Commands:

  • save_as_docx(),
  • save_as_pptx(),
  • save_as_html(),
  • save_as_image()

For interactive mode, use one of these commands:

  • print(x, preview = "docx"),
  • print(x, preview = "docx"),
  • print(x, preview = "docx"),
  • plot(x)
save_as_docx(ft, path = "reports/mario.docx",
pr_section = prop_section(
page_size = page_size(
width = 15, height = 11,
orient = "landscape"),
type = "continuous"))
save_as_pptx(ft, path = "reports/mario.pptx")
# print(ft, preview = "pptx")
plot(ft)

26 / 39

With "R Markdown" technology

Usual way:

ft <- qflextable( head( airquality ))
ft

Loops

[...] for, while, and repeat loops always return an invisible NULL, so nothing will be printed automatically [...]
https://yihui.org/en/2017/06/top-level-r-expressions/

Use chunk option results='asis' and function flextable_to_rmd:

for(i in seq_along(ft_list)){
flextable_to_rmd(ft_list[[i]])
}
27 / 39

Latest advances / unknown features

28 / 39

Documentation

User guide: https://ardata-fr.github.io/flextable-book/

 

flextable-book

Cheat sheet (not yet available), thanks to Clémentine Jager.

flextable-cheatsheet

29 / 39

Cross-references and captions

Captions are supported for HTML, PDF and Word output (also from a bookdown project with its specificities taken into account).

The recommended method to set a caption is with function set_caption.

ft <- set_caption(ft, "a correlation matrix",
autonum = run_autonum(seq_id = "tab",
bkm = "corr-table"))

But the knitr chunk options can be use instead:

  • tab.cap: Caption label
  • tab.id or label: Caption reference unique identifier, the latest is for compliance with bookdown syntax.

https://ardata-fr.github.io/flextable-book/captions-and-cross-references.html

30 / 39

PDF output

flextable supported outputs were HTML, Word and PowerPoint. This has just been extended to PDF.

  • Overall is good
  • Need some work with widths and heights management
  • No issues about that, it's not yet used by users
31 / 39

Less verbose is cool

  • set_flextable_defaults() should let you to not use font, fontsize, padding, colformat_double, etc.

  • compose gained argument use_dot: when using as_paragraph, value is evaluated within a data.frame augmented of a column named . containing the jth column.

gg_bars <- function(z) {
z <- na.omit(scale(z))
z <- data.frame(x = seq_along(z), z = z, w = z < 0)
ggplot(z, aes(x = x, y = z, fill = w)) +
geom_col(show.legend = FALSE) + theme_void()
}
dat <- as.data.table(mtcars)
z <- dat[,
lapply(.SD, function(x) list(gg_bars(x))),
by = c("vs", "am"),
.SDcols = c("mpg", "disp")
]
ft <- flextable(z)
compose(ft,
j = c("mpg", "disp"),
value = as_paragraph(
gg_chunk(value = .,
height = .15, width = 1)
),
use_dot = TRUE
)

32 / 39

Use flextable as default table output

See https://cran.r-project.org/web/packages/knitr/vignettes/knit_print.html

table_print = function(x, ...) {
flextable(x) %>% theme_vanilla()
}
# register the method
registerS3method("knit_print", "data.frame", table_print)
registerS3method("knit_print", "grouped_df", table_print)
registerS3method("knit_print", "spec_tbl_df", table_print)
registerS3method("knit_print", "tbl", table_print)
33 / 39

Miscellaneous

  • HTML rendered within shadow-dom, tables rendering was mixing flextable formattings and the web page formattings. Shadow-dom helps to keep the rendering isolated from the rest of the document.

  • Better support for non-latin alphabet in Word

set_flextable_defaults(
font.family="Arial",
cs.family = "Symbol",
eastasia.family = "仿宋")
df = data.frame(
`标题Title`='微软MS',
`内容Content`='无题lorem',
stringsAsFactors = FALSE)
print(flextable(df), preview = "docx")
  • Manuals are containing illustrations

34 / 39

Maintenance and support

36 / 39

Maintenance and support

flextable is actively maintained

Using the package, questions and help: https://stackoverflow.com/questions/tagged/flextable

Found a bug, feature request: https://github.com/davidgohel/flextable/issues

How is the maintenance organized?

  • Questions from users: documentation will be completed

  • Bugs: fix them - usually fixed within a month

  • Evolutions: if possible, no time commitment

37 / 39

Possible new features

  • RTF output, for pharmaceutical companies
  • append and prepend in cells

Path to version 1.0.0

38 / 39

Thank you

Link to GitHub repository: https://github.com/ardata-fr/flextable-whyr

Link to the presentation: https://youtu.be/-EuPFZCTnHE and https://ardata-fr.github.io/flextable-whyr

39 / 39

About me

Me and my family

Some of my open source

Funder of

Based in Paris, France

at https://www.ardata.fr

With Clémentine and Panagiotis

package development, deploiement, support, migration, shiny development

scientific cloud computing environment (jupyterhub, RStudio, ...)

R Trainings

2 / 39
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow