3MW (Creating tables with {gt})

Guten Tag!

Many greetings from Munich, Germany. The R programming language has a rich ecosystem of packages that are fantastic for creating beautiful production-grade tables from within R. No need to export your data to something like Excel or Figma to make a presentable table.

So it makes sense that our new series on Reporting tools within R features this rich table ecosystem. Today, we’re starting with one of my favorite package among the table packages, namely {gt}. 🥳 

What can {gt} do for me?

The {gt} makes it dead-simple to turn any data set into a table. To do so, this package implements what it calls the “grammar of tables” (hence the name gt.) Broadly speaking, this package

  • starts with a base function gt() - just like the {ggplot} package starts with ggplot() - and

  • passes this base layer through various {gt} functions that each target specific areas of your table.

Mini Tutorial

Fake data

Let’s first create a dummy data set using one of {gt}’s built-in data sets (there are a lot of those)

Base Layer

Now, we can just take our data and stick it into gt(). It is converted into a table as is.

Use better column names

Now, let’s add better column labels by passing our table to cols_label() via a pipe. Here, we can leave the label of the quarter column as is. Note that this only changes the displayed column names. Not the internal data column labels that we need to use in our code.

Add title & subtitle

Similarly, we can pass our modified table to the tab_header() function to add a title and a subtitle. Combine that with the md() function and we can even use Markdown style instructions like ** for bold text and back-ticks for code style.

Align columns

Next, I want to left-align the labels in the month columns. That will make that column easier to read. No problem with cols_align().

Format numbers

The numbers in the revenue column correspond to dollar amounts. Thankfully, the {gt} package has a rich set of fmt_*() functions whose purpose is to format any columns according to a specified style. One such function is fmt_currency() that turns a number column into a currency column (using USD by default.)

Add groups

Now, I want to structure my tables into quarters. The easiest way to do that is to use the quarter column in our data set for grouping. Check out what happens if we set that argument inside of the initial gt() layer.

Add summaries

And now that we have groups, we might want to also see the amount of sales and the associated revenue for these groups. A HUUUGE strength of {gt} is that it makes it really simple to add summary rows to groups (or to the table as a whole).

All you have to do is to pass your table to summary_rows() and specify

  • the columns for which you want summaries,

  • a list of lists with summary functions and associated labels, and optionally

  • a formatting function (which you have to specify via a formula using ~)

Change row height

That’s cool but now our table get’s pretty long. No problem. In the tab_options() function we have a LOOOOONG list of arguments that can specify almost anything.

Here, we can use that function to set the padding amounts (in pixels using px()) for the different parts of our table. This will make our table shorter.

Change style of summary rows

Finally, we can customize the style of any amount of cells using the tab_style() function. All this function needs is

  • the location of the cells that are to be modified (using cells_*() helper functions), and

  • the desired style that is to be applied (using cell_*() helper functions)

That way, we can add a bit of visual hierarchy to the summary rows.

More Resources

Nice! With that we have learned the basic principles of {gt}. If you want to learn more about {gt}, you may want to check out my free e-book that I wrote a while back. It’s a couple of {gt} versions behind but the overarching principles are still the same. Feel free to let me know if you find anything that doesn’t work. You can find the book at

As always, if you have any questions, or just want to reach out, feel free to contact me by replying to this mail or finding me on Linkedin.

See you next week,
Albert 👋

Enjoyed this newsletter? Here are other ways I can help you:

Reply

or to participate.