Lesson 1 of 2

Report-Ready Tables

Maya runs a neighbourhood bakery, and she is applying for a small-business loan. The bank wants her Q1 numbers, so she opens R, where her till export sits as a tidy data frame: five products, the units each one sold, the revenue, and the profit margin. She copies the raw printout straight into the application.

It comes out monospaced and unlabeled: 0.62 where she means 62%, 5520 with no dollar sign, column names like margin that only an analyst would love. The data is perfectly correct. It just does not read like something you hand to a bank. A report table fixes exactly that: a title, human column names, dollars and percentages, and a line saying where the numbers came from.

Toggle the table below between the raw print and the report version. Same five numbers, two very different first impressions.

By the end of this lesson you will be able to:

  • Build a report-ready table from a data frame with gt: a title, human column labels, and a source note
  • Format the numbers in a table: currency, percentages, and thousands separators
  • Shape the data first, sorting it and adding a share column, so the table tells a story
  • Pick the right tool for where the table will live: gt, flextable, or kableExtra

Prerequisites: you can run R and load a package with library(), and you have wrangled a data frame with dplyr (filter, mutate, arrange) in the Data Wrangling with dplyr course. Every new term is defined as it appears.

The problem

A raw print is for you. A report table is for them.

When you type a data frame's name in R, you get a printout built for you, mid-analysis: fixed-width, no styling, raw numbers. That is the right tool while you work. It is the wrong thing to put in front of a reader, who needs to glance at the table and understand it without you standing beside them.

Here is Maya's data. Each lesson runs in a fresh R session, so we build it right here (run this once), then look at the raw print:

RInteractive R
sales <- data.frame( product = c("Croissant", "Sourdough", "Blueberry Muffin", "Baguette", "Cinnamon Roll"), units = c(1840, 1210, 970, 1530, 1100), # how many sold in Q1 revenue = c(5520, 4840, 2910, 3825, 4400), # total dollars taken margin = c(0.62, 0.55, 0.48, 0.51, 0.58) # profit margin, as a proportion ) sales #> product units revenue margin #> 1 Croissant 1840 5520 0.62 #> 2 Sourdough 1210 4840 0.55 #> 3 Blueberry Muffin 970 2910 0.48 #> 4 Baguette 1530 3825 0.51 #> 5 Cinnamon Roll 1100 4400 0.58

  

The very fastest upgrade is kable() from the knitr package: one line, and you get a clean, aligned table instead of console output. It is great for a quick look or a plain document, though it stops short of titles and number formatting:

RInteractive R
library(knitr) kable(sales) #> |product | units| revenue| margin| #> |:----------------|-----:|-------:|------:| #> |Croissant | 1840| 5520| 0.62| #> |Sourdough | 1210| 4840| 0.55| #> |Blueberry Muffin | 970| 2910| 0.48| #> |Baguette | 1530| 3825| 0.51| #> |Cinnamon Roll | 1100| 4400| 0.58|

  

To go all the way to a report table, you follow the same short recipe every time. Each step adds one kind of polish: