tab_footnote()
can make it a painless process to add a footnote to a
gt table. There are commonly two components to a footnote:
(1) a footnote mark that is attached to the targeted cell content, and (2)
the footnote text itself that is placed in the table's footer area. Each unit
of footnote text in the footer is linked to an element of text or otherwise
through the footnote mark. The footnote system in gt presents footnotes
in a way that matches the usual expectations, where:
footnote marks have a sequence, whether they are symbols, numbers, or letters
multiple footnotes can be applied to the same content (and marks are always presented in an ordered fashion)
footnote text in the footer is never exactly repeated, gt reuses footnote marks where needed throughout the table
footnote marks are ordered across the table in a consistent manner (left to right, top to bottom)
Each call of tab_footnote()
will either add a different footnote to the
footer or reuse existing footnote text therein. One or more cells outside of
the footer are targeted using the cells_*()
helper
functions (e.g., cells_body()
, cells_column_labels()
, etc.). You can
choose to not attach a footnote mark by simply not specifying anything in
the locations
argument.
By default, gt will choose which side of the text to place the footnote
mark via the placement = "auto"
option. You are, however, always free to
choose the placement of the footnote mark (either to the "left
or "right"
of the targeted cell content).
Usage
tab_footnote(
data,
footnote,
locations = NULL,
placement = c("auto", "right", "left")
)
Arguments
- data
The gt table data object
obj:<gt_tbl>
// requiredThis is the gt table object that is commonly created through use of the
gt()
function.- footnote
Footnote text
scalar<character>
// requiredThe text to be used in the footnote. We can optionally use
md()
orhtml()
to style the text as Markdown or to retain HTML elements in the footnote text.- locations
Locations to target
<locations expressions>
// default:NULL
(optional
)The cell or set of cells to be associated with the footnote. Supplying any of the
cells_*()
helper functions is a useful way to target the location cells that are associated with the footnote text. These helper functions are:cells_title()
,cells_stubhead()
,cells_column_spanners()
,cells_column_labels()
,cells_row_groups()
,cells_stub()
,cells_body()
,cells_summary()
,cells_grand_summary()
,cells_stub_summary()
, andcells_stub_grand_summary()
. Additionally, we can enclose severalcells_*()
calls within alist()
if we wish to link the footnote text to different types of locations (e.g., body cells, row group labels, the table title, etc.).- placement
Placement of the footnote mark
singl-kw:[auto|right|left]
// default:"auto"
Where to affix footnote marks to the table content. Two options for this are
"left
or"right"
, where the placement is either to the absolute left or right of the cell content. By default, however, this option is set to"auto"
whereby gt will choose a preferred left-or-right placement depending on the alignment of the cell content.
Formatting of footnote text and marks
There are several options for controlling the formatting of the footnotes,
their marks, and related typesetting in the footer. All of these options are
available within tab_options()
and a subset of these are exposed in their
own opt_*()
functions.
Choosing the footnote marks
We can modify the set of footnote marks with
tab_options(..., footnotes.marks)
or opt_footnote_marks(..., )
. What that
argument needs is a vector that will represent the series of marks. The
series of footnote marks is recycled when its usage goes beyond the length of
the set. At each cycle, the marks are simply doubled, tripled, and so on
(e.g., *
-> **
-> ***
). The option exists for providing keywords for
certain types of footnote marks. The keywords are:
"numbers"
: numeric marks, they begin from1
and these marks are not subject to recycling behavior (this is the default)"letters"
: minuscule alphabetic marks, internally uses theletters
vector which contains 26 lowercase letters of the Roman alphabet"LETTERS"
: majuscule alphabetic marks, using theLETTERS
vector which has 26 uppercase letters of the Roman alphabet"standard"
: symbolic marks, four symbols in total"extended"
: symbolic marks, extends the standard set by adding two more symbols, making six
The symbolic marks are the: (1) Asterisk, (2) Dagger, (3) Double Dagger,
(4) Section Sign, (5) Double Vertical Line, and (6) Paragraph Sign; the
"standard"
set has the first four, "extended"
contains all.
Defining footnote typesetting specifications
A footnote spec consists of a string containing control characters for
formatting. They are separately defined for footnote marks beside footnote
text in the table footer (the 'spec_ftr'
) and for marks beside the targeted
cell content (the 'spec_ref'
).
Not every type of formatting makes sense for footnote marks so the specification is purposefully constrained to the following:
as superscript text (with the
"^"
control character) or regular-sized text residing on the baselinebold text (with
"b"
), italicized text (with"i"
), or unstyled text (don't use either of the"b"
or"i"
control characters)enclosure in parentheses (use
"("
/")"
) or square brackets (with"["
/"]"
)a period following the mark (using
"."
); this is most commonly used in the table footer
With the aforementioned control characters we could, for instance, format
the footnote marks to be superscript text in bold type with "^b"
. We might
want the marks in the footer to be regular-sized text in parentheses, so the
spec could be either "()"
or "(x)"
(you can optionally use "x"
as a
helpful placeholder for the marks).
These options can be set either in a tab_options()
call (with the
footnotes.spec_ref
and footnotes.spec_ftr
arguments) or with
opt_footnote_spec()
(using the spec_ref
or spec_ftr
arguments).
Additional typesetting options for footnote text residing in the footer
Within tab_options()
there are two arguments that control the typesetting
of footnotes. With footnotes.multiline
, we have a setting that determines
whether each footnote will start on a new line, or, whether they are combined
into a single block of text. The default for this is TRUE
, but, if FALSE
we can control the separator between consecutive footnotes with the
footnotes.sep
argument. By default, this is set to a single space character
(" "
).
Examples
Using a subset of the sza
dataset, let's create a new gt table. The
body cells in the sza
column will receive background color fills according
to their data values (with data_color()
). After that, the use of
tab_footnote()
lets us add a footnote to the sza
column label (explaining
what the color gradient signifies).
sza |>
dplyr::filter(
latitude == 20 &
month == "jan" &
!is.na(sza)
) |>
dplyr::select(-latitude, -month) |>
gt() |>
data_color(
columns = sza,
palette = c("white", "yellow", "navyblue"),
domain = c(0, 90)
) |>
tab_footnote(
footnote = "Color indicates the solar zenith angle.",
locations = cells_column_labels(columns = sza)
)
Of course, we can add more than one footnote to the table, but, we have to
use several calls of tab_footnote()
. This variation of the sza
table
has three footnotes: one on the "TST"
column label and two on the "SZA"
column label (these were capitalized with opt_all_caps()
). We will
ultimately have three calls of tab_footnote()
and while the order of calls
usually doesn't matter, it does have a subtle effect here since two footnotes
are associated with the same text content (try reversing the second and third
calls and observe the effect in the footer).
sza |>
dplyr::filter(
latitude == 20 &
month == "jan" &
!is.na(sza)
) |>
dplyr::select(-latitude, -month) |>
gt() |>
opt_all_caps() |>
cols_align(align = "center") |>
cols_width(everything() ~ px(200)) |>
tab_footnote(
footnote = md("TST stands for *True Solar Time*."),
locations = cells_column_labels(columns = tst)
) |>
tab_footnote(
footnote = md("SZA stands for *Solar Zenith Angle*."),
locations = cells_column_labels(columns = sza)
) |>
tab_footnote(
footnote = "Higher Values indicate sun closer to horizon.",
locations = cells_column_labels(columns = sza)
) |>
tab_options(footnotes.multiline = FALSE)
Text in the footer (both from footnotes and also from source notes) tends to
widen the table and, by extension, all the columns within it. We can limit
that by explicitly setting column width values, which is what was done above
with cols_width()
. There can also be a correspondingly large amount of
vertical space taken up by the footer since footnotes will, by default, each
start on a new line. In the above example, we used
tab_options(footnotes.multiline = FALSE)
to make it so that all footer text
is contained in a single block of text.
Let's move on to another footnote-laden table, this one based on the
towny
dataset. We have a header part, with a title and a subtitle. We
can choose which of these could be associated with a footnote and in this
case it is the "subtitle"
(one of two options in the cells_title()
helper
function). This table has a stub with row labels and some of those labels are
associated with a footnote. So long as row labels are unique, they can be
easily used as row identifiers in cells_stub()
. The third footnote is
placed on the "Density"
column label. Here, changing the order of the
tab_footnote()
calls has no effect on the final table rendering.
towny |>
dplyr::filter(csd_type == "city") |>
dplyr::arrange(desc(population_2021)) |>
dplyr::select(name, density_2021, population_2021) |>
dplyr::slice_head(n = 10) |>
gt(rowname_col = "name") |>
tab_header(
title = md("The 10 Largest Municipalities in `towny`"),
subtitle = "Population values taken from the 2021 census."
) |>
fmt_integer() |>
cols_label(
density_2021 = "Density",
population_2021 = "Population"
) |>
tab_footnote(
footnote = "Part of the Greater Toronto Area.",
locations = cells_stub(rows = c(
"Toronto", "Mississauga", "Brampton", "Markham", "Vaughan"
))
) |>
tab_footnote(
footnote = md("Density is in terms of persons per km^2^."),
locations = cells_column_labels(columns = density_2021)
) |>
tab_footnote(
footnote = "Census results made public on February 9, 2022.",
locations = cells_title(groups = "subtitle")
) |>
tab_source_note(source_note = md(
"Data taken from the `towny` dataset (in the **gt** package)."
)) |>
opt_footnote_marks(marks = "letters")
In the above table, we elected to change the footnote marks to letters
instead of the default numbers (done through opt_footnote_marks()
). A
source note was also added; this was mainly to demonstrate that source notes
will be positioned beneath footnotes in the footer section.
For our final example, let's make a relatively small table deriving from the
sp500
dataset. The set of tab_footnote()
calls used here (four of them)
have minor variations that allow for interesting expressions of footnotes.
Two of the footnotes target values in the body of the table (using the
cells_body()
helper function to achieve this). On numeric values that
right-aligned, gt will opt to place the footnote on the left of the
content so as to not disrupt the alignment. However, the placement
argument
can be used to force the positioning of the footnote mark after the content.
We can also opt to include footnotes that have no associated footnote marks
whatsoever. This is done by not providing anything to locations
. These
'markless' footnotes will precede the other footnotes in the footer section.
sp500 |>
dplyr::filter(date >= "2015-01-05" & date <="2015-01-10") |>
dplyr::select(-c(adj_close, volume, high, low)) |>
dplyr::mutate(change = close - open) |>
dplyr::arrange(date) |>
gt() |>
tab_header(title = "S&P 500") |>
fmt_date(date_style = "m_day_year") |>
fmt_currency() |>
cols_width(everything() ~ px(150)) |>
tab_footnote(
footnote = "More red days than green in this period.",
locations = cells_column_labels(columns = change)
) |>
tab_footnote(
footnote = "Lowest opening value.",
locations = cells_body(columns = open, rows = 3),
) |>
tab_footnote(
footnote = "Devastating losses on this day.",
locations = cells_body(columns = change, rows = 1),
placement = "right"
) |>
tab_footnote(footnote = "All values in USD.") |>
opt_footnote_marks(marks = "LETTERS") |>
opt_footnote_spec(spec_ref = "i[x]", spec_ftr = "x.")
Aside from changing the footnote marks to consist of "LETTERS"
, we've also
changed the way the marks are formatted. In our use of opt_footnote_spec()
,
the spec_ref
option governs the footnote marks across the table. Here, we
describe marks that are italicized and set between square brackets (with
"i[x]"
). The spec_ftr
argument is used for the footer representation of
the footnote marks. As described in the example with "x."
, it is rendered
as a footnote mark followed by a period.
See also
Other part creation/modification functions:
tab_caption()
,
tab_header()
,
tab_info()
,
tab_options()
,
tab_row_group()
,
tab_source_note()
,
tab_spanner()
,
tab_spanner_delim()
,
tab_stub_indent()
,
tab_stubhead()
,
tab_style()
,
tab_style_body()