Skip to content
R for the Rest of Us Logo

How to Make Beautiful Tables in R

David Keyes David Keyes
November 12th, 2019

Updated March 12, 2022 with info on the reactablefmtr and gtextras packages.

Want to learn to make beautiful tables?

It doesn't matter how good your data analysis is if you don't effectively communicate your results. In most reports, communication of results happens through a combination of data visualization and tables. Along with narrative text, these make up the bulk of content used to communicate results.

Clear writing is a topic for another venue. Data visualization in R is a huge topic (and one covered expertly in Kieran Healy's Data Visualization: A Practical Introduction and Claus Wilke's Fundamentals of Data Visualization). But what about tables? Fortunately for R users, there are many ways to create beautiful tables that effectively communicate your results.

Customizing Default Table Output in RMarkdown

If you are using RMarkdown (and, if you're not, you should really consider it), any data frame that you call in a code chunk is displayed using the data frame printing method set in your YAML. As Yihui Xie puts it, "printing objects in R code chunks basically emulates the R console." This default output leaves much to be desired. "Table" output with fixed-width fonts like this never inspired anyone to take action.

The ubiquitous default output format

It is quite easy to improve this output. You can change the default data frame print method in the YAML to one of the following options.

Screenshot from RMarkdown: The Definitive Guide

Of these, the one most likely to improve your table output is paged, which creates paged tables that work well when you have particularly long tables and want to give users the ability to look at pieces of the output:

My Favorite R Packages to Make Tables

There are also many packages that provide functions to produce nicely formatted tables. Here are some of the packages I have used that produce tables that look good and effectively communicate results.


gt is a new(ish) package. It “is designed to be both straightforward yet powerful … [with] an emphasis is on simple functions for the everyday display table needs.” The package has functions designed to do things like:

  • Modify the locations of outputs

  • Format text as well as background shading

  • Add titles, subtitles, captions, etc.

Screenshot from RMarkdown: The Definitive Guide

The gt package provides a general philosophy of tables (similar to the grammar of graphics theory that underlies the ggplot2 package) that enables it to be easy to use (with some practice) and extremely flexible.

Learn more about gt


There’s also a package called gtextras that provides add-ons for the gt package. This package, by Thomas Mock, provides some nice themes like this modeled on New York Times tables.

The package also lets you add visualizations into tables, including sparklines and bar plots.

Learn more about gtextras.

kable + kableExtra

The kableExtra package builds on the kable output from the knitr package. As author Hao Zhu puts it:

The goal of kableExtra is to help you build common complex tables and manipulate table styles. It imports the pipe %>% symbol from magrittr and verbalize all the functions, so basically you can add “layers” to a kable output in a way that is similar with ggplot2 and plotly.

Sharla Gelfand used the kableExtra package in a report she did for the College of Nurses of Ontario and loved it.

Learn more about kableExtra


Kun Ren's formattable package" is designed for applying formatting on vectors and data frames to make data presentation easier, richer, more flexible and hopefully convey more information."

One of the most unique features is the ability to add colors, background shading, bars, and other features that move tables beyond hulking blocks of text.

If you're looking for an example of the formattable package in use, Laura Ellis has a really nice walkthrough.

Learn more about formattable


The main appeal of the DT package is its ability to add filtering, pagination, and sorting to HTML tables. Users can slice, scroll through, and arrange tables in ways that help them to make sense of your results.

Learn more about DT


I had not heard of this package until Mara Averick tweeted about it recently. Though I haven't used it, the docs look incredible. Like the DT package, it offers the ability to sort and filter data. It's also much more visually appealing than the DT package. One of the examples (below) looks exactly like the gorgeous tables made by FiveThirtyEight.

Learn more about reactable


The reactable package can be a bit more challenging to work with. To simplify the process of creating tables in reactable, Kyle Cuilla developed the reactablefmtr package. As Kyle puts it:

The {reactablefmtr} package simplifies and enhances the styling and formatting of tables built with the {reactable} R package. The {reactablefmtr} package provides many conditional formatters that are highly customizable and easy to use.

Among other things, the reactablefmtr package makes it easier to conditionally add colors to tables, add interactive sparklines, use custom themes, embed images in tables, and save tables in PNG and HTML format.

Example table using the reactablefmtr package with conditional colors, images, and a custom theme.

Learn more about reactablefmtr


The above packages are designed to produce HTML tables. If you are knitting to Word, your best for tables is the flextable package (though the tables this package produces can also be embedded within HTML and PDF outputs). Designed by David Gohel, the flextable package provides a straightforward syntax to shape the content and format of your tables.

Learn more about flextable

Packages Recommended by Others

The above packages are ones that I've used and had good success with. When I put the call out on Twitter for other packages to make tables in R, I got some promising-looking responses!


The huxtable package produces:

LaTeX and HTML tables, with a friendly, modern interface. Features include control over text styling, number format, background color, borders, padding and alignment. Cells can span multiple rows and/or columns. Tables can be manipulated with standard R subsetting or dplyr functions.

Learn more about huxtable


Like the DT package, the rhandsontable package gives users the ability to manipulate data in tables. It comes with "powerful features like data validation, sorting, grouping, data binding, formula support or column ordering." Working with tables feels like viewing data in Excel, which can be helpful for users used to working with Microsoft's ubiquitous spreadsheet program. Users can even make changes to data in tables made with this package.

Learn more about rhandsontable


The fantastically-named pixedust package is designed to produce a specific type of table: model output that has been tidied using the broom package. Using pixiedust is a three-step process:

  1. Run your model using a base R function (e.g. lm for a linear model)

  2. Use the tidy function from the broom package to convert the results into a tidy format

  3. Use the pixiedust package (the sprinkle_ set of functions in particular) to improve the output, removing “stats-speak” and putting it into a “format that is suitable for publication or submission to a client.”

The sprinkle_ functions enable you to do things like removing excess decimal places, convert p-values to not use scientific notation, and more.

If you want to ensure that end users read and understand the results of your complex statistical analyses, this looks like a great package!

Learn more about pixiedust

There are surely more table packages that I've missed (in wrapping up this post, I came across this list from the RStudio RMarkdown tutorials), but this should give you a good place to start in making your tables more beautiful and more effective.

Let us know what you think by adding a comment below.

You need to be signed-in to comment on this post. Login.