You can create tables with custom formatting in Displayr by writing some R code. This lets you go beyond the table styles that are available in the Appearance menu. Formatted table outputs can be created in R by making use of packages like DT and formattable. In this post I look at a simple example that can be created with the DT (short for Data Tables) package.

DT provides an R interface for the DataTables JavaScript library, which is used on the web for creating interactive and customized tables for web pages. DT produces tables with interactive elements, like column filtering and sorting, searching within the table, and the table spread over multiple pages. These can all be turned on or off as needed.

The process for customizing tables is fairly advanced, and using it successfully will require a bit of knowledge about HTML (and perhaps some trial-and-error). In this post I use a fairly simple example - I change the background colors and fonts in the table. To get an idea of the other options and formatting that are available, check out the developer's page on GitHub. I will introduce the components of the customization in stages.  To see the final block of code I used, check out the very end of the post.

The basic process for creating your tables is as follows:

  1. Prepare the data that will be shown in the table.
  2. Choose which interactive options you want to keep.
  3. Create the formatting for the table header.
  4. Create the formatting for the table rows labels.
  5. Add the formatting for the separate columns.

Data preparation

To create a customized table, you need to begin with some tabular data. In this example I will use a standard crosstab, created by dragging variables from Data Sets on to the page. You can also use Home > Data > Paste Table to paste in data you have computed elsewhere, or use a table computed with R.

When supplying numeric results, the DT tables will show all available decimal places. This means that you should round your data appropriately before creating the table. In our example we round the inputs to zero decimal places before drawing the table.

To make the table easy to refer to in our code, we select Properties > GENERAL > Name in the Object Inspector, and change it to original.table. This is how the table will be accessed when writing code.


The default DT table

Without manipulating formatting or tweaking any of the options, the DT table will look as follows.

The elements at the top and bottom of the table are interactive (try clicking on them!). They will also be interactive for people who view your published document. In the following example I  turn them all off, but you can choose to keep any of them in your table if you wish.

To begin, select Insert > R Output, and enter the code to construct your table. The code which generated this table is:

library(DT)
dd = round(original.table, 0)
vanilla.table = datatable(dd,
                          rownames = TRUE, # Do not treat table row names as separate column
                          width = '100%', # Ensure table remains within the dimensions of the container
                          height = '100%') # Ensure table remains within the dimensions of the container

In this code I have:

  • Rounded the input data.
  • Called the datatable() function, which produces the table.
  • Used the rownames argument to tell the table that the labels on the left are to be treated as row names (as opposed to another column of data).
  • Set the width and height to 100% to ensure the table is drawn within the box that Displayr provides.

Turning off the options

The interactive options of the table can be modified via the options argument to datatable().

my.options <- list(autoWidth = FALSE,
                   searching = FALSE,
                   ordering = FALSE,
                   lengthChange = FALSE,
                   lengthMenu = FALSE,
                   pageLength = FALSE,
                   paging = FALSE,
                   info = FALSE)

With all of the interactive elements turned off, the data table looks like this:

See the final example for how the options are used when creating the data table.


Formatting the header

The table header is formatted by constructing a container argument. A container is an HTML snippet that allows you to specify the CSS for each column header. In our example, I construct the container using the withTags function from the htmltools package. In this example, I set the background color to red, and the font color to white. The HTML container also specifies the alignment of the text and the properties of the borders between the cells. In this example I use the same style for each column, but you could also create separate styles for different columns.

header.style <- "th { font-family: 'Arial'; font-weight: bold; color: white; background-color: #ed1c16;}"
header.names <- c(" ", colnames(dd))
# The container parameter allows us to design the header of the table
# using CSS
my.container <-  withTags(table(
    style(type = "text/css", header.style),
    thead(
        tr(
                lapply(header.names, th, style = "text-align: center; border-right-width: 1px; border-right-style: solid; border-right-color: white; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: white")
        )
    )
))

In this code:

  • header.style specifies the style for the table header
  • header.names contains the names for each column, starting with a blank label for the first column (which contains the row labels)
  •  my.container uses the withTags function to construct the HTML container, combining the overall table style along with a style for each individual column header

Adding the container argument to the datatable call produces the following table. See the final example for how the container is included.


Formatting the row labels

To format the columns of the table, which in our case includes the column that contains the row labels, the formatStyle() function is applied. This function allows for formatting of fonts, colors, borders, padding within cells, and more. In this case, the most obvious formatting that I've applied is to change the color of the cells, and the font, but settings are also specified for the borders and padding.

Columns may be formatted in groups or separately by successive applications of formatStyle. Columns can be specified by their position, from left to right, or by their label (as specified above  in the container). In this case, the header label for the first column was " " (in the header.names variable above), and so I use this to tell the formatStyle function which column to format (see below).

The result is:


Formatting the cells of the table

As with the row labels, the remaining columns of the table are formatted using formatStyle. I apply the same formatting to each of the remaining three columns in the table. Column indexes start at zero, so I supply columns 1, 2, and 3.

This time, I use a grey background, and for maximum impact I use a bold red font. The final appearance of our custom table is:

The complete code used to draw this table is as follows:

library(DT)
library(htmltools)

dd = round(original.table, 0)

my.options <- list(autoWidth = FALSE,
                   searching = FALSE,
                   ordering = FALSE,
                   lengthChange = FALSE,
                   lengthMenu = FALSE,
                   pageLength = FALSE,
                   paging = FALSE,
                   info = FALSE)

header.style <- "th { font-family: 'Arial'; font-weight: bold; color: white; background-color: #ed1c16;}"
header.names <- c(" ", colnames(dd))
# The container parameter allows us to design the header of the table
# using CSS
my.container <-  withTags(table(
    style(type = "text/css", header.style),
    thead(
        tr(
                lapply(header.names, th, style = "text-align: center; border-right-width: 1px; border-right-style: solid; border-right-color: white; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: white")
        )
    )
))


my.table = datatable(dd,
                     options = my.options,
                     container = my.container,
                     rownames = TRUE, # Do not treat table row names as separate column
                     width = '100%', # Ensure table remains within the dimensions of the container
                     height = '100%') # Ensure table remains within the dimensions of the container



# Format row names in red
my.table <- formatStyle(my.table,
                        columns = " ",
                        backgroundColor = "rgb(237, 28, 22)",
                        borderBottomColor = "rgb(255, 255, 255)",
                        borderBottomStyle = "solid",
                        borderBottomWidth = "1px",
                        borderCollapse = "collapse",
                        borderRightColor = "rgb(255, 255, 255)",
                        borderRightStyle = "solid",
                        borderRightWidth = "1px",
                        color = "rgb(255, 255, 255)",
                        fontFamily = "Arial",
                        fontSize = "13px",
                        fontWeight = "bold",
                        lineHeight = "normal",
                        paddingBottom = "2.6px",
                        paddingLeft = "5.2px",
                        paddingRight = "5.2px",
                        paddingTop = "2.6px",
                        textAlign = "left",
                        verticalAlign = "middle")

#Format cells of table with grey background and bold red font
my.table <- formatStyle(my.table,
                        columns = c(1,2,3),
                        fontFamily = "Arial",
                        fontSize = "16px",
                        color = '#ed1c16',
                        fontWeight = 'bold',
                        paddingRight = "1em",
                        borderRightWidth = "1px",
                        borderRightStyle = "solid",
                        borderRightColor = "white",
                        borderBottomColor = "rgb(255, 255, 255)",
                        borderBottomStyle = "solid",
                        borderBottomWidth = "1px",
                        borderCollapse = "collapse",
                        verticalAlign = "middle",
                        textAlign = "center",
                        wordWrap = "break-word",
                        backgroundColor = '#e6e6e5')

my.table