htmlwidgets - DT #
The Bigger Picture #
In this document we learn how to create interactive tables with DT. Simply put, we are learning how to transform tidy data into visually clear tables. In the overall context of the workflow, this falls into the category of transforming our data into data visualisation.
What is DT? #
library("tidyverse")
library("DT")
- An htmlwidget used to make interactive data tables from data frames and tibbles
- It is arguably the best R package for this specific purpose
- The package is bound to the DataTable library in JavaScript
Creating Interactive Tables #
Let’s say we have a dataset, such as the set below from the ACORN-SAT dataset. Note that we are deliberately using a large dataset (this one contains around 6000 observations)
load("tidy_ACORN-SAT_data/station_data.rdata")
head(station_data, 8)
## Number year average.temp Station.name Latitude Longitude Elevation Start
## 1 2012 1910 26.4 Halls Creek -18.23 127.66 422 1910
## 2 3003 1910 27.3 Broome -17.95 122.24 7 1910
## 3 6011 1910 21.5 Carnarvon -24.89 113.67 4 1910
## 4 7045 1910 21.8 Meekatharra -26.61 118.54 517 1926
## 5 9021 1910 18.0 Perth Airport -31.93 115.98 15 1910
## 6 9518 1910 16.3 Cape Leeuwin -34.37 115.14 13 1910
## 7 9789 1910 16.7 Esperance -33.83 121.89 25 1910
## 8 10917 1910 15.0 Wandering -32.67 116.67 275 1910
With DT, we can instantly make this an interactive table by using the pipeline (%>%
) operator and piping our data into the datatable()
function.
station_data %>%
datatable()
We immediately have an interactive table. The remainder of this tutorial will address how to tweak the table we have. Currently here are some of the things we can do:
- View our data in an aesthetic table
- Show 10, 25, 50 or 100 observations at a given time using the drop-down menu
- View the another page of observations with the page feature below the table
- Click on the arrows next to the column names to order our observations in ascending or descending order by that variable name
- Search with the search bar for the occurence of a string in any column of an observation
- Try typing “Tarcoola”
- Now try typing “25.” What do you notice?
Additional Options #
We notice that the first ‘column’ is just a number representing which observation of the table we are looking at. This is generally of no purpose to us, so we can remove it using the rownames
argument of datatable()
. We set it to FALSE
.
station_data %>%
datatable(rownames = FALSE)
We also notice some of our column names are not very aesthetic. We can make them more so by:
- Using the
gsub()
andstringr::str_to_title()
functions to create a list of nicer names - Using the
colnames
argument ofdatatable()
to change these names
The following command replaces all dots (.
s) with spaces, then capitalises the first letter of each word, and stores the new set of names in the column_title
variable.
column_titles <- gsub("[.]", " ", colnames(station_data)) %>%
stringr::str_to_title()
column_titles
## [1] "Number" "Year" "Average Temp" "Station Name" "Latitude"
## [6] "Longitude" "Elevation" "Start"
We now use these as the new column names with colnames
:
station_data %>%
datatable(rownames = FALSE,
colnames = column_titles)
We can already search for a given term in our data, but if we want to search for a term in a single column, we can add individual column filters using the filter
argument.
- This argument takes a list of sub-arguments as its value
- We set the
position
sub-argument to “top” or “bottom” to add our filter
station_data %>%
datatable(rownames = FALSE,
colnames = column_titles,
filter = list(position = "top"))
If we wish to display a number of observations which is not 10, 25, 50 or 100, we can use the options
argument,
- This argument takes a list of sub-arguments as its value
- We set the
pageLength
sub-argument to the number of observations we wish to display
station_data %>%
datatable(rownames = FALSE,
colnames = column_titles,
options = list(pageLength = 7))
Now say we wish to modify the search bar so that it doesn’t say “Search:” but instead “Keyword look-up:”
- We still use the
options
argument ofdatatable()
- We use the sub-argument
language
ofoptions
, which itself takes a list as its argument - We use the sub-sub-argument
sSearch
to rename the search bar
station_data %>%
datatable(rownames = FALSE,
colnames = column_titles,
options = list(pageLength = 7,
language = list(sSearch = "Keyword look-up:")))
Formatting Values in Tables #
Sometimes we will wish to display data in specific formats, such as dollars ($
), a percentage (%
) or otherwise. We have specific functions in DT for each of these.
sample_price %>%
datatable()
If we wish to format a column as a currency, we pipe our table into formatCurrency()
:
- The first argument is the column to format (as a string!!!)
- We then use the
currency
argument to select the currency we want (as a character)
sample_price %>%
datatable() %>%
formatCurrency("Amount_Spent",
currency = "$")
If we were dealing in another currency, such as the Japanese Yen, we can specify an alternate currency:
sample_price %>%
datatable() %>%
formatCurrency("Amount_Spent",
currency = "¥")
If we wish to change the decimal places displayed, we use the additional argument digits
:
sample_price %>%
datatable() %>%
formatCurrency("Amount_Spent",
currency = "$") %>%
formatCurrency("Budget",
currency = "$",
digits = 0)
Let’s say we now want to display the percentage of our budget we have spent.
sample_price <- sample_price %>%
mutate(Portion_Spent = Amount_Spent / Budget)
sample_price
## # A tibble: 6 x 4
## Date Budget Amount_Spent Portion_Spent
## <chr> <dbl> <dbl> <dbl>
## 1 21-06-2019 50 49.2 0.984
## 2 22-06-2019 50 47.2 0.944
## 3 23-06-2019 50 41.8 0.836
## 4 24-06-2019 50 52.0 1.04
## 5 25-06-2019 50 52.9 1.06
## 6 26-06-2019 50 37.8 0.755
We use the formatPercentage()
function, specifying:
- The column to format as the first argument
- The number of decimal places we require as the
digits
argument
sample_price %>%
datatable() %>%
formatCurrency("Amount_Spent",
currency = "$") %>%
formatCurrency("Budget",
currency = "$",
digits = 0) %>%
formatPercentage("Portion_Spent",
digits = 2)
Lastly, if we wish to format dates, we use the formatDate()
function:
- We specify the column to format as the first argument
- We specify the method by which to format in the
method
column- We generally assign “toDateString,” but a full list of methods can be found here
sample_price %>%
datatable() %>%
formatCurrency("Amount_Spent",
currency = "$") %>%
formatCurrency("Budget",
currency = "$",
digits = 0) %>%
formatPercentage("Portion_Spent",
digits = 2) %>%
formatDate("Date",
method = "toDateString")
Here the date formating failed. The reason for this is that the “Date” column contains strings of D-M-Y formatted dates. The formatDate()
function requires entries of class ‘date,’ not strings. We can fix this using the lubridate
package.
- We mutate our Date column
- We use the
dmy()
function oflubridate
because our dates are in D-M-Y format - The entries are reclassified as dates
class(sample_price$Date)
## [1] "character"
library("lubridate")
sample_price <- sample_price %>%
mutate(Date = dmy(Date))
class(sample_price$Date)
## [1] "Date"
sample_price %>%
datatable() %>%
formatCurrency("Amount_Spent",
currency = "$") %>%
formatCurrency("Budget",
currency = "$",
digits = 0) %>%
formatPercentage("Portion_Spent",
digits = 2) %>%
formatDate("Date",
method = "toDateString")
Options for Responsive Tables #
If we have tables with lots of columns, we have options to truncate these.
(Sample data provided by Climate Change in Australia)
fire_data %>%
datatable(rownames = FALSE,
options = list(pageLength = 5))
The simplest method is using the argument extensions
of datatable()
.
- We can set this to “Responsive” to truncate columns
- These can then be viewed for individual data points
fire_data %>%
datatable(rownames = FALSE,
extensions = "Responsive",
options = list(pageLength = 5))
We now have a +
button that displays columns which can’t fit on our screen. There is, however, an even more responsive solution which allows the reader to select and deselect columns for viewing as they like. This requires some setup:
- We set the
extensions
argument to a vector containing “Responsive” and “Buttons” (ie `c(“Responsive,” “Buttons”)) - We add the sub-argument
buttons
to theoptions
argument ofdatatable()
- This takes the value of
I("colvis")
since we want the column-visability button- Note: the reason we wrap this in the
I()
function is technical and relates to the formatting of DT
- Note: the reason we wrap this in the
- We add the sub-argument
dom
to theoptions
argument ofdatatable()
- This takes the value of “Bf” for our purposes
- More on
dom
below
- More on
fire_data %>%
datatable(rownames = FALSE,
extensions = c("Responsive", "Buttons"),
options = list(pageLength = 5,
buttons = I("colvis"),
dom = "Bf"))
We now have a “Column visibility” button we can use to toggle columns as displayed and hidden.
More on the dom
Argument
#
This argument controls much about what we see in our tables. The argument is always a string, but, unlike many arguments we have seen in R, it is the individual letters of the string that are important.
In the above example, “Bf” means we desire B
uttons and f
ilter to be enabled, in that order. There are actually many letters we can use to enhance or change our table (several of which are described
here). We may be interested in:
Letter | Function |
---|---|
l |
Enables length changing control |
f |
Enables the global filter |
t |
The table itself (*) |
i |
Table information summary |
p |
Page number navigation |
B |
Buttons (assuming they have been properly set up) |
(*) Of course the table is always enabled, but this option is important in controlling order. For example, if we want the filter to be below the table, we use dom = "tf"
:
station_data %>%
datatable(rownames = FALSE,
options = list(pageLength = 5,
dom = "tf"))
As another example, consider the argument “Bpiltf,” structuring the widget, from top to bottom, as buttons, page-navigation, summary info, length changing, the table, and the filter below:
station_data %>%
datatable(rownames = FALSE,
extensions = c("Responsive", "Buttons"),
options = list(pageLength = 5,
buttons = I("colvis"),
dom = "Bpiltf"))
Lastly, as a fun example, consider that we are not limited to just one of each letter:
station_data %>%
datatable(rownames = FALSE,
options = list(pageLength = 5,
dom = "ppfptpf"))
Maybe this would not be such a good idea in practice!
Allowing Users to Download Table Data #
We can add a button which allows users to download the data as it appears in our table.
- Users may download the content straight from (for example) your HTML webpage
- Users also may filter or remove columns and download the modified table
To do this is very similar to how we added the “colvis” buttons:
- Include the
extensions
argument ofdatatable()
- Set this to
c("Responsive", "Buttons")
- Include the
options
argument ofdatatable()
- Set this to a list, containing the sub-argument
buttons
- Set the value of this sub-argument to a vector of “excel” and “csv”
station_data %>%
datatable(rownames = FALSE,
extensions = c("Responsive", "Buttons"),
options = list(pageLength = 5,
buttons = c("colvis", "excel", "csv"),
dom = "Bf"))