Create a color-mapping function for continuous numeric values.
col_numeric(
palette=None,
domain=None,
midpoint=None,
stops=None,
na_color=None,
reverse=False,
truncate=False,
)
The col_numeric() helper returns a function that linearly maps numeric values onto a color palette (interpolating between the palette’s colors). The returned function is designed to be passed to the fn= argument of data_color(), but it can be called on any list of values.
Parameters
palette: str | list[str] | None = None
-
The colors to interpolate between. This can be a list of colors (as hexadecimal values or color names) or the name of a ColorBrewer or viridis palette (see data_color() for the available names). If None, then a default palette will be used.
domain: list[int] | list[float] | None = None
-
The range of values to map onto the palette, given as [min, max]. Values outside of this range receive the missing-value color (unless truncate=True). If None, then the domain is taken from the range of the (non-missing) values supplied to the returned function each time it is called (or, with midpoint=, a range made symmetric around the midpoint). This can’t be used together with stops=.
midpoint: int | float | None = None
-
A value that receives the color at the center of the palette. If domain= is None, then the domain is made symmetric around the midpoint, reaching as far as the value furthest from it. If domain= is supplied, then each side of the midpoint is scaled separately to its end of the domain (and the midpoint must lie within the domain). This works in the same way as the midpoint= argument of data_color() and can’t be used together with stops=.
stops: list[int | float | str] | None = None
-
A list giving the value at which each palette color is reached, with one entry per color in the palette (after any ColorBrewer or viridis palette name is expanded). Colors are interpolated between neighboring stops. Each stop can be either a number (a data value) or a percentage string from "0%" to "100%" (a position within the range of the values supplied to the returned function, extended to include any numeric stops). For example, stops=["0%", 0, "100%"] pins the lowest value, zero, and the highest value, whatever the range of the values. Stops must be in non-decreasing order once resolved. A repeated stop creates a sharp change between two colors, with a value exactly at that stop taking the later color. The outermost stops act as the domain, so values beyond them receive the missing-value color (unless truncate=True).
na_color: str | None = None
-
The color to use for missing values and values outside of the domain. If None, then the returned function gives None for those values, which lets data_color() apply its own na_color= color.
reverse: bool = False
-
Should the order of the palette colors be reversed? This doesn’t affect stops=, which apply to the colors in their reversed order.
truncate: bool = False
-
If
True, then values outside of the domain (or the outermost stops=) are treated as the nearest end of it, so they receive the first or last color of the palette. If False (the default), then they receive the missing-value color.
Returns
Callable[[list[Any]], list[str | None]]
-
A function that takes a list of numeric values and returns a list of hexadecimal colors.
Examples
A diverging palette with a domain centered on zero colors negative values increasingly red and positive values increasingly green, the further they are from zero:
import pandas as pd
from great_tables import GT, col_numeric
df = pd.DataFrame(
{
"region": ["North", "South", "East", "West", "Central"],
"change": [12.5, -8.1, 0.0, 3.2, -1.0],
}
)
GT(df).data_color(
columns="change",
fn=col_numeric(palette=["#D7191C", "white", "#1A9641"], domain=[-15, 15]),
)
| region |
change |
| North |
12.5 |
| South |
-8.1 |
| East |
0.0 |
| West |
3.2 |
| Central |
-1.0 |
Rather than fixing the domain, we can give a midpoint=. The domain is then made symmetric around the midpoint, reaching as far as the value furthest from it:
GT(df).data_color(
columns="change",
fn=col_numeric(palette=["#D7191C", "white", "#1A9641"], midpoint=0),
)
| region |
change |
| North |
12.5 |
| South |
-8.1 |
| East |
0.0 |
| West |
3.2 |
| Central |
-1.0 |
With stops=, every palette color can be pinned to a value. Stops can be data values or percentages of the way through the range of values. Here, the lowest value is fully red, zero is white, and the highest value is fully green, so each side uses its full range of colors:
GT(df).data_color(
columns="change",
fn=col_numeric(palette=["#D7191C", "white", "#1A9641"], stops=["0%", 0, "100%"]),
)
| region |
change |
| North |
12.5 |
| South |
-8.1 |
| East |
0.0 |
| West |
3.2 |
| Central |
-1.0 |
Repeating a stop makes a sharp change in color at that value. Here, values below zero are shades of orange and values from zero up are shades of purple:
GT(df).data_color(
columns="change",
fn=col_numeric(
palette=["#E66101", "#FDB863", "#B2ABD2", "#5E3C99"],
stops=["0%", 0, 0, "100%"],
),
)
| region |
change |
| North |
12.5 |
| South |
-8.1 |
| East |
0.0 |
| West |
3.2 |
| Central |
-1.0 |
With a narrower domain, truncate=True saturates the colors of values beyond its limits rather than leaving them uncolored. Here, anything above 5 is fully green and anything below -5 is fully red:
GT(df).data_color(
columns="change",
fn=col_numeric(palette=["#D7191C", "white", "#1A9641"], domain=[-5, 5], truncate=True),
)
| region |
change |
| North |
12.5 |
| South |
-8.1 |
| East |
0.0 |
| West |
3.2 |
| Central |
-1.0 |