boxenplot
Mojo function 🡭
boxenplot
fn def boxenplot(df: DataFrame, category: String, value: String, theme: Theme = Theme(WHITE, Color(UInt8(30), UInt8(100), UInt8(180), UInt8(255)), Color(UInt8(80), UInt8(80), UInt8(80), UInt8(255)), Color(UInt8(225), UInt8(225), UInt8(225), UInt8(255)), Color(UInt8(40), UInt8(40), UInt8(40), UInt8(255)), SIMD(12), SIMD(3.5), SIMD(2), Int(60), Int(20), Int(20), Int(50), True, False, False, Color(UInt8(240), UInt8(240), UInt8(240), UInt8(255)), Int(3), Color(UInt8(60), UInt8(110), UInt8(200), UInt8(255)), Color(UInt8(235), UInt8(235), UInt8(235), UInt8(255)), Color(UInt8(220), UInt8(90), UInt8(40), UInt8(255)), ColorRamp(), ColorPalette(), SIMD(3), SIMD(15), True, SIMD(1), Int(0), False, Color(UInt8(200), UInt8(60), UInt8(60), UInt8(255)), Color(UInt8(224), UInt8(224), UInt8(224), UInt8(255)), Color(UInt8(120), UInt8(120), UInt8(120), UInt8(255)), Color(UInt8(100), UInt8(100), UInt8(100), UInt8(255)), Color(UInt8(230), UInt8(230), UInt8(230), UInt8(255)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), UInt8(90), UInt8(160), False, False, SIMD(0), SIMD(18), SIMD(14), Color(UInt8(110), UInt8(110), UInt8(110), UInt8(255)), SIMD(14), Color(UInt8(150), UInt8(150), UInt8(150), UInt8(255)), Color(UInt8(224), UInt8(236), UInt8(246), UInt8(200)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), True, False, False, True, AxisPosition.EDGE, AxisPosition.EDGE, String("sans-serif"), True, UInt8(90), Int(5), Int(4), Int(130), Int(14), Int(8), Int(14), Int(100), Int(8), SIMD(4), OutputFormat.SVG, Tooltips.AUTO, Missing.DRAW, String("(missing)"), Int(1000), False, LineStyle.SOLID, SIMD(1.5), LineStyle.SOLID, LegendPosition.RIGHT, XAxisLabelRotation.AUTO, TickFormat.AUTO, TickFormat.AUTO), width: Int = Int(640), height: Int = Int(420), title: String = "", subtitle: String = "", x_title: String = "", y_title: String = "", horizontal: Bool = False) -> Chart[Boxenplot]boxenplot() over a long-form dataframe_mojo DataFrame (#743): one row per observation, with category naming each row’s group and value holding the number.
A frame stores these long while the mark wants one list per
category, so the rows are bucketed by category, in first-appearance
order. The axis titles default to the two column names.
Args:
- df (
DataFrame): The frame to read. - category (
String): The string column naming each observation’s group. - value (
String): The numeric column holding the observations. - theme (
Theme): Full styling knobs beyond this function’s own parameters. - width (
Int): Pixel width of the returnedPlot(.size()). - height (
Int): Pixel height of the returnedPlot(.size()). - title (
String): The chart’s title, shown above the plot. - subtitle (
String): A line under the title. - x_title (
String): The x-axis caption; defaults tocategory. - y_title (
String): The y-axis caption; defaults tovalue. - horizontal (
Bool): Draw the categories down the y axis instead.
Returns:
Chart[Boxenplot]: The finished chart – unrendered.
Raises:
Error: A named column is missing, has the wrong dtype for its channel, or has missing values.
fn def boxenplot[dtype: DType](categories: List[String], values: List[List[Scalar[dtype]]], theme: Theme = Theme(WHITE, Color(UInt8(30), UInt8(100), UInt8(180), UInt8(255)), Color(UInt8(80), UInt8(80), UInt8(80), UInt8(255)), Color(UInt8(225), UInt8(225), UInt8(225), UInt8(255)), Color(UInt8(40), UInt8(40), UInt8(40), UInt8(255)), SIMD(12), SIMD(3.5), SIMD(2), Int(60), Int(20), Int(20), Int(50), True, False, False, Color(UInt8(240), UInt8(240), UInt8(240), UInt8(255)), Int(3), Color(UInt8(60), UInt8(110), UInt8(200), UInt8(255)), Color(UInt8(235), UInt8(235), UInt8(235), UInt8(255)), Color(UInt8(220), UInt8(90), UInt8(40), UInt8(255)), ColorRamp(), ColorPalette(), SIMD(3), SIMD(15), True, SIMD(1), Int(0), False, Color(UInt8(200), UInt8(60), UInt8(60), UInt8(255)), Color(UInt8(224), UInt8(224), UInt8(224), UInt8(255)), Color(UInt8(120), UInt8(120), UInt8(120), UInt8(255)), Color(UInt8(100), UInt8(100), UInt8(100), UInt8(255)), Color(UInt8(230), UInt8(230), UInt8(230), UInt8(255)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), UInt8(90), UInt8(160), False, False, SIMD(0), SIMD(18), SIMD(14), Color(UInt8(110), UInt8(110), UInt8(110), UInt8(255)), SIMD(14), Color(UInt8(150), UInt8(150), UInt8(150), UInt8(255)), Color(UInt8(224), UInt8(236), UInt8(246), UInt8(200)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), True, False, False, True, AxisPosition.EDGE, AxisPosition.EDGE, String("sans-serif"), True, UInt8(90), Int(5), Int(4), Int(130), Int(14), Int(8), Int(14), Int(100), Int(8), SIMD(4), OutputFormat.SVG, Tooltips.AUTO, Missing.DRAW, String("(missing)"), Int(1000), False, LineStyle.SOLID, SIMD(1.5), LineStyle.SOLID, LegendPosition.RIGHT, XAxisLabelRotation.AUTO, TickFormat.AUTO, TickFormat.AUTO), width: Int = Int(640), height: Int = Int(420), title: String = "", subtitle: String = "", x_title: String = "", y_title: String = "", horizontal: Bool = False) -> Chart[Boxenplot]A letter-value plot: like box(), but the single box and two whiskers become nested boxes at successively finer quantiles – the quartiles, then the eighths, the sixteenths and on – each half as wide as the last, with only the observations beyond the deepest box drawn as points.
A box plot is the right summary for a small sample and a poor one
for a large one: with thousands of observations “outlier” under the
1.5 IQR rule stops meaning anything, and the whiskers plus a cloud
of points say nothing about the shape of the tail. This draws the
tail instead of discarding it. How deep the nest goes follows the
sample size (Tukey’s rule, floor(log2(n)) - 3 levels), so a small
sample gets a plain quartile box and a large one several levels.
Mark.BOXENPLOT over encode_boxenplot().
Example:
from dataviz import boxenplot, save
def main() raises:
# Illustrative page-load times (ms) for three deployments, 256
# samples each with a long right tail -- the case a box plot's
# outlier cloud says nothing useful about.
var names: List[String] = ["v1", "v2", "v3"]
var samples = List[List[Float64]]()
for d in range(3):
var s = List[Float64]()
var seed = 7 + d
for _ in range(256):
seed = (seed * 1103515245 + 12345) % 2147483648
var u = Float64(seed % 10000) / 10000.0
# Skewed: most loads are quick, a few are very slow.
s.append(120.0 + 40.0 * Float64(d) + 900.0 * u * u * u)
samples.append(s^)
var chart = boxenplot(
names,
samples,
title="Illustrative Page-Load Time by Deployment",
y_title="Load time (ms)",
)
save(chart, "docs/src/examples/out_boxenplot.svg")Parameters:
- dtype (
DType)
Args:
- categories (
List[String]): One label per group. - values (
List[List[Scalar[dtype]]]):values[i]is every raw observation incategories[i]. - theme (
Theme): Full styling knobs beyond this function’s own arguments. - width (
Int): Canvas width in pixels. - height (
Int): Canvas height in pixels. - title (
String): Chart title; empty for none. - subtitle (
String): Chart subtitle; empty for none. - x_title (
String): X-axis title; empty for none. - y_title (
String): Y-axis title; empty for none. - horizontal (
Bool): Draw categories top-to-bottom with values running left-to-right.
Returns:
Chart[Boxenplot]: The finished Plot, ready to render() or save().
Raises:
Error: categories and values differ in length, or a group is
empty.