View source: R/tab_create_modify.R
tab_spanner | R Documentation |
With tab_spanner()
, you can insert a spanner in the column labels part of a
gt table. This part of the table contains, at a minimum, column labels
and, optionally, an unlimited number of levels for spanners. A spanner will
occupy space over any number of contiguous column labels and it will have an
associated label and ID value. This function allows for mapping to be defined
by column names, existing spanner ID values, or a mixture of both. The
spanners are placed in the order of calling tab_spanner()
so if a later call
uses the same columns in its definition (or even a subset) as the first
invocation, the second spanner will be overlaid atop the first. Options exist
for forcibly inserting a spanner underneath other (with level
as space
permits) and with replace
, which allows for full or partial spanner replacement.
tab_spanner(
data,
label,
columns = NULL,
spanners = NULL,
level = NULL,
id = label,
gather = TRUE,
replace = FALSE
)
data |
The gt table data object
This is the gt table object that is commonly created through use of the
|
label |
Spanner label text
The text to use for the spanner label. We can optionally use |
columns |
Columns to target
The columns to serve as components of the spanner. Can either be a series
of column names provided in |
spanners |
Spanners to target
The spanners that should be spanned over, should they already be defined.
One or more spanner ID values (in quotes) can be supplied here. This
argument works in tandem with the |
level |
Spanner level for insertion
An explicit level to which the spanner should be placed. If not provided,
gt will choose the level based on the inputs provided within In combination with |
id |
Spanner ID
The ID for the spanner. When accessing a spanner through the |
gather |
Gather columns together
An option to move the specified |
replace |
Replace existing spanners
Should new spanners be allowed to partially or fully replace existing
spanners? (This is a possibility if setting spanners at an already
populated |
An object of class gt_tbl
.
columns
argumentThe columns
argument allows us to target a subset of columns contained in
the table. We can declare column names in c()
(with bare column names or
names in quotes) or we can use tidyselect-style expressions. This can be
as basic as supplying a select helper like starts_with()
, or, providing a
more complex incantation like
where(~ is.numeric(.x) && max(.x, na.rm = TRUE) > 1E6)
which targets numeric columns that have a maximum value greater than
1,000,000 (excluding any NA
s from consideration).
Let's take a hypothetical table that includes the following column names in
order from left to right: year
, len.pop
, m.pop
, len.dens
, and
m.dens
. We'd like to have some useful spanners, but don't want to have any
over the year
column (so we'll avoid using that column when defining
spanners). Let's start by creating a schematic representation of what is
wanted in terms of spanners:
| ------- `"Two Provinces of Ireland"` ------ <- level 2 spanner | ---- `"Leinster"` ---- | --- `"Munster"` -- <- level 1 spanners `year` | `len.pop` | `len.dens` | `m.pop` | `m.dens` <- column names ----------------------------------------------------
To make this arrangement happen, we need three separate calls of
tab_spanner()
:
tab_spanner(., label = "Leinster", columns = starts_with("len"))
tab_spanner(., label = "Munster", columns = starts_with("m"))
tab_spanner(., label = "Two Provinces of Ireland", columns = -year)
This will give us the spanners we need with the appropriate labels. The ID
values will be derived from the labels in this case, but they can directly
supplied via the id
argument.
An important thing to keep aware of is that the order of calls matters. The
first two can be in any order but the third one must happen last since we
build spanners from the bottom up. Also note that the first calls will
rearrange columns! This is by design as the gather = TRUE
default will
purposefully gather columns together so that the columns will be united under
a single spanner. More complex definitions of spanners can be performed and
the Examples section demonstrates some of the more advanced calls of
tab_spanner()
.
As a final note, the column labels (by default deriving from the column
names) will likely need to change and that's especially true in the above
case. This can be done with either of cols_label()
or cols_label_with()
.
Measurement units are often seen as part of spanner labels and indeed it can
be much more straightforward to include them here rather than using other
devices to make readers aware of units for specific columns. Any text
pertaining units is to be defined alongside the spanner label. To do this, we
have to surround the portion of text in the label that corresponds to the
units definition with "{{"
/"}}"
.
Now that we know how to mark text for units definition, we know need to know how to write proper units with the notation. Such notation uses a succinct method of writing units and it should feel somewhat familiar though it is particular to the task at hand. Each unit is treated as a separate entity (parentheses and other symbols included) and the addition of subscript text and exponents is flexible and relatively easy to formulate. This is all best shown with a few examples:
"m/s"
and "m / s"
both render as "m/s"
"m s^-1"
will appear with the "-1"
exponent intact
"m /s"
gives the the same result, as "/<unit>"
is equivalent to
"<unit>^-1"
"E_h"
will render an "E"
with the "h"
subscript
"t_i^2.5"
provides a t
with an "i"
subscript and a "2.5"
exponent
"m[_0^2]"
will use overstriking to set both scripts vertically
"g/L %C6H12O6%"
uses a chemical formula (enclosed in a pair of "%"
characters) as a unit partial, and the formula will render correctly with
subscripted numbers
Common units that are difficult to write using ASCII text may be implicitly
converted to the correct characters (e.g., the "u"
in "ug"
, "um"
,
"uL"
, and "umol"
will be converted to the Greek mu symbol; "degC"
and "degF"
will render a degree sign before the temperature unit)
We can transform shorthand symbol/unit names enclosed in ":"
(e.g.,
":angstrom:"
, ":ohm:"
, etc.) into proper symbols
Greek letters can added by enclosing the letter name in ":"
; you can
use lowercase letters (e.g., ":beta:"
, ":sigma:"
, etc.) and uppercase
letters too (e.g., ":Alpha:"
, ":Zeta:"
, etc.)
The components of a unit (unit name, subscript, and exponent) can be
fully or partially italicized/emboldened by surrounding text with "*"
or
"**"
Let's create a gt table using a small portion of the gtcars
dataset.
Over several columns (hp
, hp_rpm
, trq
, trq_rpm
, mpg_c
, mpg_h
)
we'll use tab_spanner()
to add a spanner with the label "performance"
.
This effectively groups together several columns related to car performance
under a unifying label.
gtcars |> dplyr::select( -mfr, -trim, bdy_style, -drivetrain, -trsmn, -ctry_origin ) |> dplyr::slice(1:8) |> gt(rowname_col = "model") |> tab_spanner( label = "performance", columns = c( hp, hp_rpm, trq, trq_rpm, mpg_c, mpg_h ) )
With the default gather = TRUE
option, columns selected for a particular
spanner will be moved so that there is no separation between them. This can
be seen with the example below that uses a subset of the towny
dataset.
The starting column order is name
, latitude
, longitude
,
population_2016
, density_2016
, population_2021
, and density_2021
. The
first two uses of tab_spanner()
deal with making separate spanners for the
two population and two density columns. After their use, the columns are
moved to this new ordering: name
, latitude
, longitude
,
population_2016
, population_2021
, density_2016
, and density_2021
. The
third and final call of tab_spanner()
doesn't further affect the ordering
of columns.
towny |> dplyr::slice_max(population_2021, n = 5) |> dplyr::select( name, latitude, longitude, ends_with("2016"), ends_with("2021") ) |> gt() |> tab_spanner( label = "Population", columns = starts_with("pop") ) |> tab_spanner( label = "Density", columns = starts_with("den") ) |> tab_spanner( label = md("*Location*"), columns = ends_with("itude"), id = "loc" )
While columns are moved, it is only the minimal amount of moving required
(pulling in columns from the right) to ensure that columns are gathered under
the appropriate spanners. With the last call, there are two more things to
note: (1) label
values can use the md()
(or html()
) helper functions to
help create styled text, and (2) an id
value may be supplied for reference
later (e.g., for styling with tab_style()
or applying footnotes with
tab_footnote()
).
It's possible to stack multiple spanners atop each other with consecutive
calls of tab_spanner()
. It's a bit like playing Tetris: putting a spanner
down anywhere there is another spanner (i.e., there are one or more shared
columns) means that second spanner will reside a level above the prior. Let's
look at a few examples to see how this works, and we'll also explore a few
lesser-known placement tricks. We'll use a cut down version of exibble
for this, set up a few level-1
spanners, and then place a level-2
spanner
over two other spanners.
exibble_narrow <- exibble |> dplyr::slice_head(n = 3) exibble_narrow |> gt() |> tab_spanner( label = "Row Information", columns = c(row, group) ) |> tab_spanner( label = "Numeric Values", columns = where(is.numeric), id = "num_spanner" ) |> tab_spanner( label = "Text Values", columns = c(char, fctr), id = "text_spanner" ) |> tab_spanner( label = "Numbers and Text", spanners = c("num_spanner", "text_spanner") )
In the above example, we used the spanners
argument to define where the
"Numbers and Text"
-labeled spanner should reside. For that, we supplied the
"num_spanner"
and "text_spanner"
ID values for the two spanners
associated with the num
, currency
, char
, and fctr
columns.
Alternatively, we could have given those column names to the columns
argument and achieved the same result. You could actually use a combination
of spanners
and columns
to define where the spanner should be placed.
Here is an example of just that:
exibble_narrow_gt <- exibble_narrow |> gt() |> tab_spanner( label = "Numeric Values", columns = where(is.numeric), id = "num_spanner" ) |> tab_spanner( label = "Text Values", columns = c(char, fctr), id = "text_spanner" ) |> tab_spanner( label = "Text, Dates, Times, Datetimes", columns = contains(c("date", "time")), spanners = "text_spanner" ) exibble_narrow_gt
And, again, we could have solely supplied all of the column names to
columns
instead of using this hybrid approach, but it is interesting to
express the definition of spanners with this flexible combination.
What if you wanted to extend the above example and place a spanner above the
date
, time
, and datetime
columns? If you tried that in the manner as
exemplified above, the spanner will be placed in the third level of spanners:
exibble_narrow_gt |> tab_spanner( label = "Date and Time Columns", columns = contains(c("date", "time")), id = "date_time_spanner" )
Remember that the approach taken by tab_spanner()
is to keep stacking atop
existing spanners. But, there is space next to the "Text Values"
spanner on
the first level. You can either revise the order of tab_spanner()
calls,
or, use the level
argument to force the spanner into that level (so long
as there is space).
exibble_narrow_gt |> tab_spanner( label = "Date and Time Columns", columns = contains(c("date", "time")), level = 1, id = "date_time_spanner" )
That puts the spanner in the intended level. If there aren't free locations
available in the level
specified you'll get an error stating which columns
cannot be used for the new spanner (this can be circumvented, if necessary,
with the replace = TRUE
option). If you choose a level higher than the
maximum occupied, then the spanner will be dropped down. Again, these
behaviors are indicative of Tetris-like rules which tend to work well for the
application of spanners.
Using a subset of the towny
dataset, we can create an interesting gt
table. First, only certain columns are selected from the dataset, some
filtering of rows is done, rows are sorted, and then only the first 10 rows
are kept. After the data is introduced to gt()
, we then apply some spanner
labels using two calls of tab_spanner()
. In the second of those, we
incorporate unit notation text (within "{{"
/"}}"
) in the label
to get a
display of nicely-formatted units.
towny |> dplyr::select( name, ends_with(c("2001", "2006")), matches("2001_2006") ) |> dplyr::filter(population_2001 > 100000) |> dplyr::slice_max(pop_change_2001_2006_pct, n = 10) |> gt() |> fmt_integer() |> fmt_percent(columns = matches("change"), decimals = 1) |> tab_spanner( label = "Population", columns = starts_with("population") ) |> tab_spanner( label = "Density, {{*persons* km^-2}}", columns = starts_with("density") ) |> cols_label( ends_with("01") ~ "2001", ends_with("06") ~ "2006", matches("change") ~ md("Population Change,<br>2001 to 2006") ) |> cols_width(everything() ~ px(120))
2-2
v0.2.0.5
(March 31, 2020)
tab_spanner_delim()
to create spanners and new column labels with
delimited column names.
Other part creation/modification functions:
tab_caption()
,
tab_footnote()
,
tab_header()
,
tab_info()
,
tab_options()
,
tab_row_group()
,
tab_source_note()
,
tab_spanner_delim()
,
tab_stub_indent()
,
tab_stubhead()
,
tab_style()
,
tab_style_body()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.