col_numeric()

Create a color-mapping function for continuous numeric values.

Usage

Source

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