density_outline ¶
Outlines of a 2D point cloud at a fraction of its peak density, computed in Rust.
Not in lets-plot. density_outline() evaluates a Gaussian kernel density with a
full covariance (as scipy.stats.gaussian_kde) on a padded grid and traces the
contour at level times its peak by marching squares (as
skimage.measure.find_contours), so outlines need neither scipy nor scikit-image.
The result is a polars frame to draw with geom_path.
Bandwidth
module-attribute
¶
Bandwidth = typing.Literal['scott', 'silverman'] | float
Represent a union type
E.g. for int | str
Pairs
module-attribute
¶
Pairs = (
collections.abc.Sequence[
collections.abc.Sequence[float]
]
| ggrust.density_outline._ArrayLike
)
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
density_outline ¶
density_outline(
points: Pairs,
*,
level: float = 0.1,
padding: float = 1.0,
grid_size: int = 200,
bandwidth: Bandwidth = "scott",
) -> pl.DataFrame
Outline a 2D point cloud where its kernel density falls to level of the peak.
The density is a Gaussian kernel estimate with a full covariance (the data
covariance scaled by the bandwidth factor, as scipy.stats.gaussian_kde).
It is evaluated on a grid_size by grid_size grid spanning the points'
bounding box widened by padding on every side, and the contour at
level * peak is traced by marching squares, as
skimage.measure.find_contours. The vertices match that scipy and
scikit-image recipe to about 1e-15. Draw the result with geom_path.
Parameters:
-
points((n, 2) array) –Point coordinates, one
(x, y)row per point: a numpy array, nested sequences or a two-column data frame. Rows with a non-finite coordinate (or a masked entry) are dropped; at least 3 points must remain, and they must not lie on one line. -
level(float, default:0.1) –Outline level as a fraction of the peak density, between 0 and 1 (exclusive). Lower values draw a wider outline that takes in sparse points.
-
padding(float, default:1.0) –Space added to each side of the points' bounding box before gridding, in data units. Too little padding cuts low-level outlines open at the grid edge.
-
grid_size(int, default:200) –Grid points per axis, from 2 to 3162. Higher values give smoother outlines; the work grows with
grid_size ** 2times the number of points. -
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 deviations.
Returns:
-
DataFrame–One row per outline vertex:
xandy(Float64) andpath(UInt32, the outline number from 0, foraes(group="path")). Closed outlines repeat their first vertex. A cloud with several dense spots can give several outlines; alevelthe density never crosses gives none.
Raises:
-
SpecError–If
pointsis not an(n, 2)array of numbers, fewer than 3 finite points remain, the points lie on one line, or an option is out of range.
Examples:
>>> import math
>>> from ggrust import *
>>> points = [[math.cos(i) * (i % 7) / 7, math.sin(i) * (i % 5) / 5] for i in range(200)]
>>> outline = density_outline(points, level=0.1, padding=0.5, grid_size=80)
>>> outline.columns
['x', 'y', 'path']
>>> outline["path"].unique().to_list()
[0]
>>> plot = (
... ggplot()
... + geom_point(aes("x", "y"), data={"x": [p[0] for p in points],
... "y": [p[1] for p in points]}, size=1)
... + geom_path(aes("x", "y", group="path"), data=outline, linetype="dashed")
... + coord_fixed()
... )