Skip to content

Footnotes everywhere

Here we'll showcase how to place footnotes in three different places.

TargetConstructor
Column header:col => "note"
Spanner labelSpannerTarget(label) => "note"
Body cellCellTarget(row, col) => "note"
julia
using StyledTables, DataFrames

df = DataFrame(
    country  = ["United States", "Germany", "Japan"],
    gdp_usd  = [25.5, 4.1, 4.2],
    gdp_ppp  = [27.3, 5.2, 6.2],
    pop_m    = [331, 84, 125],
)
3×4 DataFrame
Rowcountrygdp_usdgdp_ppppop_m
StringFloat64Float64Int64
1United States25.527.3331
2Germany4.15.284
3Japan4.26.2125

Column footnotes

Typically, all we want and need is to annotate a single column name:

julia
tbl = StyledTable(df)
footnote!(tbl,
    [:gdp_usd, :gdp_ppp] => "Trillions USD, 2025",
    [:pop_m] => "Millions",
)
render(tbl)
country gdp_usd1 gdp_ppp1 pop_m2
United States 25.5 27.3 331
Germany 4.1 5.2 84
Japan 4.2 6.2 125
1 Trillions USD, 2025
2 Millions

Spanner footnotes

When we're using column spanners and our footnote applies to all columns under that spanner, we of course don't want to target all these column names with the same footnote. Instead, we can use SpannerTarget to annotate only the spanner label:

julia
tbl = StyledTable(df)
spanner!(tbl, [:gdp_usd, :gdp_ppp] => "GDP (Trillions)")
footnote!(tbl, SpannerTarget("GDP (Trillions)") => "Estimated values")
render(tbl)
GDP (Trillions)1
country gdp_usd gdp_ppp pop_m
United States 25.5 27.3 331
Germany 4.1 5.2 84
Japan 4.2 6.2 125
1 Estimated values

Cell footnotes

Last but not least, we may also want to annotate specific values in our table. We do this by targetting cells using CellTarget. You can specify the cell location in two ways:

By row index (1-based):

julia
tbl = StyledTable(df)
japan_gdp_ppp = CellTarget(3, :gdp_ppp)
footnote!(tbl, japan_gdp_ppp => "Preliminary estimate")
render(tbl)
country gdp_usd gdp_ppp pop_m
United States 25.5 27.3 331
Germany 4.1 5.2 84
Japan 4.2 6.21 125
1 Preliminary estimate

By stub value (requires stub!):

If a stub column exists, you may target rows by the stub value rather than the numeric index. This option offers better readability over numeric indices, and if you expect your rows to change order it is also the more robust and maintainable choice.

julia
tbl = StyledTable(df)
stub!(tbl, :country)
japan_gdp_ppp = CellTarget(Stub("Japan"), :gdp_ppp)
footnote!(tbl, japan_gdp_ppp => "Preliminary estimate")
render(tbl)
gdp_usd gdp_ppp pop_m
United States 25.5 27.3 331
Germany 4.1 5.2 84
Japan 4.2 6.21 125
1 Preliminary estimate