Skip to content

kernel_density

One-dimensional Gaussian kernel densities at given points, computed in Rust.

Not in lets-plot. kernel_density() evaluates the density of a set of values at points the caller picks, as scipy.stats.gaussian_kde(values)(at) (Scott's or Silverman's rule, or a bandwidth factor), so custom density shapes such as violins drawn by hand need no scipy. stat_density and geom_violin keep lets-plot's bandwidths; this function is for densities built outside a layer.

Bandwidth module-attribute

Bandwidth = typing.Literal['scott', 'silverman'] | float

Represent a union type

E.g. for int | str

Values module-attribute

Values = (
    collections.abc.Sequence[float]
    | ggrust.kernel_density._ArrayLike
    | polars.series.series.Series
)

Represent a union type

E.g. for int | str

SpecError

SpecError(
    message: str, *, path: str = "", reason: str = ""
)

Bases: ggrust.errors.GgrustError, builtins.ValueError

Raised when the plot specification holds an invalid value.

Parameters:

  • message (str) –

    The full message, including the location.

  • path (str, default: "" ) –

    Spec path of the offending value, e.g. "layers[0].size" or "theme.axis_text.size"; empty when the error concerns the whole spec.

  • reason (str, default: "" ) –

    What was wrong and what is accepted, without the location.

Examples:

>>> from ggrust import *
>>> from ggrust.errors import SpecError
>>> data = {"weight": [2.6, 2.9, 3.2, 3.4, 3.6, 4.1], "mpg": [31, 28, 24, 22, 19, 15]}
>>> chart = ggplot(data, aes("weight", "mpg")) + geom_point(shape="star")
>>> try:
...     svg = chart.to_svg()
... except SpecError as error:
...     print(error.path)
layers[0].shape

kernel_density

kernel_density(
    values: Values,
    at: Values,
    *,
    bandwidth: Bandwidth = "scott",
) -> pl.DataFrame

Evaluate the Gaussian kernel density of values at the points at.

The kernel is a Gaussian whose standard deviation is the data standard deviation (unbiased) times the bandwidth factor, and the density is the mean of the kernels centered on the values, as scipy.stats.gaussian_kde. The result matches gaussian_kde(values, bw_method=bandwidth)(at) to about 1e-14 of the peak density for values centered within a few standard deviations of zero. Values offset from zero by k standard deviations lose about k units in the last place in both scipy and ggrust (rounding of the scaled values), so they agree only to about k * 1e-15 there. Use it to build density shapes outside a layer, for example violins placed by hand; stat_density and geom_violin follow lets-plot's bandwidths instead.

Parameters:

  • values (sequence of float, numpy array or polars Series) –

    The sample, one dimension (booleans count as 0 and 1). Non-finite and missing values are dropped; at least 2 must remain, and they must not all be equal.

  • at (sequence of float, numpy array or polars Series) –

    Points to evaluate the density at, one dimension, in any order. A non-finite point gives a NaN density.

  • bandwidth ((scott, silverman), default: 'scott' ) –

    Kernel bandwidth: Scott's or Silverman's rule (scipy's bw_method), or a positive factor that multiplies the data standard deviation.

Returns:

  • DataFrame –

    One row per point of at, in its order: x (the point) and density (Float64). The density integrates to 1 over the real line.

Raises:

  • SpecError –

    If values or at is not a one-dimensional set of numbers, fewer than 2 finite values remain, they are all equal, or bandwidth is invalid.

Examples:

>>> from ggrust import *
>>> waiting = [54, 55, 56, 57, 58, 60, 62, 75, 76, 78, 79, 80, 81, 82, 83, 85, 88]
>>> grid = [40 + i for i in range(61)]
>>> density = kernel_density(waiting, grid)
>>> density.columns
['x', 'density']
>>> density["x"][density["density"].arg_max()]
80.0
>>> plot = ggplot(density, aes("x", "density")) + geom_area(alpha=0.4) + geom_line()