Site icon R-bloggers

Table It Like a Pro: Print-Ready Tables in R

[This article was first published on Numbers around us - Medium, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

You’ve probably been there — mention to someone that you work with data, and they say, “Oh, so you just make tables?” Tables, right? How hard could it be? It’s just rows and columns. But we know better, don’t we? Tables aren’t just a random dumping ground for numbers; they’re the quiet superheroes of the data world. They give structure to chaos, they summarize the story our data is trying to tell, and they can make or break how well our insights land with an audience.

For us, a well-crafted table is more than just numbers on a page — it’s a tool of communication, a piece of art (well, almost), and a key part of our data workflow.

The Unsung Heroes: Why Tables Matter in Data Analysis

Tables might not get the same attention as those slick graphs or shiny dashboards, but don’t be fooled — they’re the real workhorses behind the scenes. Sure, charts are great for showing trends or making things visual, but when it comes to details, tables take the crown. Let’s face it, when you need to communicate something concrete and precise, you reach for a table.

Think about your day-to-day as a data person. How many times have you had to provide a summary for a project? Or maybe your boss asks for a snapshot of key performance indicators (KPIs), or someone needs to see how metrics have changed over time. What’s your go-to solution? Yep, a table.

Tables are the Swiss Army knives of data presentation — they can do pretty much anything. They’re ideal when you need to:

But tables aren’t just about dumping numbers in neat rows and columns. A well-made table can tell a story, condensing complex information into something a reader can scan in seconds and still get all the key insights. A bad table? That’s a surefire way to confuse people, overload them with data, and make sure no one actually reads what you’re trying to say.

Good tables help bridge the gap between raw data and the story it’s telling. For example, let’s say you’re analyzing sales performance. A simple table can show sales by region, by product, by time period — you name it. Suddenly, what was just a sea of numbers becomes a meaningful comparison: “Oh look, sales in the Northeast jumped by 20% this quarter, while the Southwest dipped slightly.”

It’s this flexibility and power that make tables such an important part of our job. And let’s be honest — whether you’re sending off reports to a client or presenting your findings to your team, a well-crafted table can make you look like you’ve got your act together. It says, “Hey, I didn’t just throw some data together — I organized it.”

Tables are the unsung heroes because they do the grunt work of presenting detailed information without the flash — but with all the substance. In the end, they’re not just about presenting data; they’re about ensuring that data is understood.

Tables in R: More Than Meets the Eye

Now that we’ve set the stage for why tables are so crucial, let’s talk about how R makes it all happen. If you’re new to R, you might think creating tables is as simple as printing out a few rows and columns — and sure, that’s one way to start. But as you’ll see, there’s so much more you can do.

Let’s begin with the basics. If you’ve got a dataset loaded into R, you can print it right to your console with something as simple as print() or even just calling the object’s name. It’s quick, it’s dirty, and it works when you need to peek at your data. But the real power comes when you start to customize your output, because let’s face it, the default look of console tables? Pretty bare-bones.

For a quick improvement, you’ve got kable() from the knitr package, which lets you turn basic R output into nicely formatted Markdown tables. It’s a great way to start if you’re looking to add tables directly into documents, be they Markdown, HTML, or PDF. Here’s a simple example:

library(knitr)

# Basic table in Markdown
kable(head(mtcars), format = "markdown")

This gives you a clean, easy-to-read table that can fit right into your R Markdown reports. It’s simple, but it instantly upgrades the way your data is presented. Whether you’re working on an internal project or sending off client-facing reports, you want your tables to be clear, and kable() makes that happen with minimal effort.

Printing Tables to PDFs, Word Docs, and HTML

Now, let’s step it up a notch. What if you need to include your tables in more polished reports — like a PDF or Word document? R has your back with the rmarkdown and officer packages. These allow you to knit your R scripts directly into these formats, and — bonus! — they keep your tables looking slick.

For example, if you’re knitting to a PDF document, you can still use kable() for your tables. Here’s a quick look at how you can do that:

---
title: "My PDF Report"
output: pdf_document
---

```{r}
library(knitr)
kable(head(mtcars), format = "latex")
```

By switching the format to latex, you’re telling R to produce a PDF-ready table. But what if your boss (or client) loves Word documents? Not a problem! With officer, you can generate tables in a .docx file that look sharp and professional. Here’s a quick peek at how to do that:

library(officer)
library(flextable)

doc <- read_docx()

# Add a title and table
doc <- body_add_par(doc, "Table of Cars", style = "heading 1")
doc <- body_add_flextable(doc, flextable(head(mtcars)))

print(doc, target = "my_report.docx")

Suddenly, you’ve got a Word document with a table that looks like it belongs in a professional report. This is the kind of flexibility that makes R such a powerhouse when it comes to data presentation — whether you’re generating quick Markdown tables or polished Word and PDF documents.

Leveling Up: Working with Excel in R

Excel is still a big deal in many workplaces, and let’s be honest, it’s not going anywhere. If you’re handling reports, budgets, or performance tracking, chances are good that someone’s going to ask you for an Excel file. Luckily, R can easily handle Excel files — whether you’re reading data in or exporting results out.

Reading and Writing Excel Files

First up, let’s talk about reading from Excel. With the readxl package, importing an Excel file into R is as simple as calling read_excel(). But what if you want to export your data from R into an Excel-friendly format? That’s where openxlsx or writexl come in. Here’s how you can take a dataset like the ggplot2::diamonds dataset and write it to an Excel file:

library(openxlsx)
library(ggplot2)

# Taking a sample of the diamonds dataset for demo
diamonds_sample <- diamonds[sample(nrow(diamonds), 100), ]

# Writing the data to an Excel file
write.xlsx(diamonds_sample, "diamonds_sample.xlsx", sheetName = "Diamonds Sample")

With this, you’ve written a sample of the diamonds dataset to an Excel file with just a couple of lines. You can quickly export your data, whether it’s a quick analysis or a detailed report, for others to work with in Excel.

Handling Excel Workbooks and Formatting

What if you need more than just one simple table — let’s say multiple sheets, or maybe you want to add some styling to make the data presentation look polished? openxlsx gives you full control over these things.

Let’s go ahead and create a workbook with two sheets: one containing a sample of the diamonds dataset and another with a summary of the data. Plus, we’ll add some styling to make the Excel file look professional.

# Create a new workbook
wb <- createWorkbook()

# Add two worksheets
addWorksheet(wb, "Diamonds Data")
addWorksheet(wb, "Summary")

# Write the diamonds sample data to the first sheet
writeData(wb, sheet = "Diamonds Data", diamonds_sample)

# Create a summary of the diamonds dataset
summary_data <- data.frame(
  Mean_Price = mean(diamonds_sample$price),
  Median_Carat = median(diamonds_sample$carat),
  Max_Price = max(diamonds_sample$price)
)

# Write the summary to the second sheet
writeData(wb, sheet = "Summary", summary_data)

# Apply styling to the header of the Diamonds Data sheet
headerStyle <- createStyle(textDecoration = "bold", Colour = "#FFFFFF", fgFill = "#4F81BD")
addStyle(wb, sheet = "Diamonds Data", style = headerStyle, rows = 1, cols = 1:ncol(diamonds_sample), gridExpand = TRUE)

# Save the workbook
saveWorkbook(wb, "styled_diamonds_report.xlsx", overwrite = TRUE)

Here’s what this code does:

The ability to customize the style, structure, and formatting of your Excel workbooks directly from R can save tons of time. Plus, automating this kind of report generation ensures consistency and professionalism.

Tables aren’t confined to R alone — thanks to these tools, you can seamlessly move your data between R and Excel, and even bring R’s automation power into Excel workflows.

Formatting Excellence: Creating Print-Ready Tables with gt and Friends

So, you’ve got your data ready, and you’ve generated some tables. But here’s the thing — those default tables may not cut it when you’re aiming for a professional, polished look. Whether you’re preparing a report for stakeholders or a publication for a journal, you’ll want your tables to shine. That’s where the gt package comes in.

gt stands for “Grammar of Tables,” and it’s a fantastic package for creating high-quality, beautifully formatted tables in R. It gives you control over almost every aspect of your table’s appearance—from styling text and adding footnotes to adjusting column widths and more.

Creating Your First Table with gt

Let’s start by creating a simple, yet nicely formatted table using the gt package. We’ll use the ggplot2::diamonds dataset again to generate a table with a few key columns, and we’ll style it for a professional look:

library(gt)
library(ggplot2)

# Take a small sample of the diamonds dataset for our table
diamonds_sample <- diamonds[sample(nrow(diamonds), 5), ]

# Create a basic gt table
gt_table <- gt(diamonds_sample) %>%
  tab_header(
    title = "Diamonds Data Sample",
    subtitle = "A snapshot of key attributes"
  ) %>%
  fmt_number(
    columns = c(carat, price),
    decimals = 2
  ) %>%
  cols_label(
    carat = "Carat Weight",
    cut = "Cut Quality",
    color = "Diamond Color",
    clarity = "Clarity Rating",
    price = "Price (USD)"
  ) %>%
  tab_style(
    style = list(
      cell_text(weight = "bold")
    ),
    locations = cells_column_labels(everything())
  ) %>%
  tab_footnote(
    footnote = "Data from ggplot2's diamonds dataset.",
    locations = cells_title(groups = "title")
  )

# Print the table
gt_table

In this example, we:

With gt, this table looks polished and ready for a report or presentation, not just a quick console dump. The customization options mean you can make your tables look exactly the way you want them.

Exporting Tables to HTML, PDF, and More

One of the best things about gt is that it’s not just for the console. You can easily export your tables to different formats—like HTML for web pages or LaTeX for PDFs. Here’s how you can export the table we just created:

# Save the table as an HTML file
gtsave(gt_table, "diamonds_table.html")

# Or save it as a PNG image
gtsave(gt_table, "diamonds_table.png")e

This flexibility lets you integrate your tables into various types of reports, whether you’re working on a web-based report, a PDF for publication, or just need a static image for presentations.

Using kableExtra for More Advanced Formatting

If you need even more advanced table customization, kableExtra is another excellent package to explore. It extends kable() from the knitr package, allowing for advanced formatting like row grouping, column spanning, and more.

Here’s an example of a nicely formatted table using kableExtra, which allows for more complex layouts, like adding row groups:

In this case:

With kableExtra, you can quickly add professional touches like multi-level headers, row grouping, or different visual styles.

Why Use These Formatting Packages?

Whether you go with gt for its user-friendly table creation and stunning formatting options, or kableExtra for more advanced customization, the goal is the same: producing polished, professional-looking tables that do more than just hold data—they communicate it clearly and attractively. These packages transform your tables from a plain grid into something that enhances your reports, presentations, or publications.

By now, it should be clear that tables are more than just a simple way to display data — they’re a powerful tool for communicating insights, presenting results, and helping others make sense of the story your data is telling. From basic console prints to beautifully formatted, publication-ready tables, R offers a wide variety of tools to turn raw data into organized, insightful tables that look as good as they perform.

We’ve explored how to:

As you’ve seen, tables are far from “just tables.” They’re the unsung heroes of data analysis, bringing structure and clarity to even the most complex datasets. With the right tools and formatting, they can elevate your work and make your data-driven reports stand out.

What’s Next? Interactive Tables!

Now that we’ve mastered the art of creating print-ready tables in R, it’s time to take things a step further. In the next article, we’ll dive into the world of interactive tables — exploring how to add sorting, filtering, and more using R’s powerful toolkits like Shiny, R Markdown, and Quarto. Imagine tables where users can engage with your data, making it even easier to explore and understand.

Get ready to make your tables not just informative but interactive. Stay tuned!


Table It Like a Pro: Print-Ready Tables in R was originally published in Numbers around us on Medium, where people are continuing the conversation by highlighting and responding to this story.

To leave a comment for the author, please follow the link and comment on their blog: Numbers around us - Medium.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Exit mobile version