Box Plot for Delivery Times by Carrier
You are a logistics manager, and a customer has just complained about a parcel that took eleven days. Which carrier was it, and is that one bad parcel or a habit? Five carriers, six deliveries each: an average per carrier hides exactly the late ones you are asked about. A box plot answers it. Each carrier gets a box for the middle half of its deliveries, a line at the median, whiskers for the usual range, and a dot for every delivery far outside it.
The live example starts with every carrier together. The chart is bound to the grid, so it draws exactly the rows the grid is showing. Put the word Meridian in the box, or open the filter on the Carrier column, and the chart redraws for those rows on the next frame.
Why a box plot and not a bar chart
A bar of average delivery days gives Swiftway and Meridian a respectable height and says nothing about the one parcel that took nine or eleven days. The box plot keeps the spread, so a tight, reliable carrier and a mostly fast one with a long tail look different, which is the difference your complaints come from.
The chart is a view of the grid
There is no second data set to keep in step. createChart takes the grid itself, reads its filtered rows, and redraws whenever they change. x names the carrier and y the delivery days to summarise for each one. Filter out a carrier, or a row, and the chart follows, because a chart of rows you cannot see would be describing a different network.
The code, in plain JavaScript
import { createGrid } from '@toclocoinc/lattice-grid';
import { createChart } from '@toclocoinc/lattice-grid/modules/charts';
import '@toclocoinc/lattice-grid/css';
const days = {
Northline: [2, 2, 3, 3, 3, 4], 'Harbor Freight': [3, 4, 4, 5, 5, 6],
Swiftway: [1, 2, 2, 2, 3, 9], Meridian: [3, 3, 4, 4, 5, 11],
Redhill: [4, 5, 6, 6, 7, 8],
};
const rows = Object.entries(days).flatMap(([carrier, list], i) =>
list.map((d, j) => ({ id: i * 6 + j + 1, carrier, days: d })));
const grid = createGrid(document.querySelector('#grid'), {
rowKey: 'id',
columns: [
{ field: 'carrier', title: 'Carrier', filter: { type: 'set' } },
{ field: 'days', title: 'Delivery days', type: 'number' },
],
rows,
});
createChart({
grid, container: '#chart', type: 'boxplot',
x: 'carrier', y: 'days', title: 'Delivery days by carrier',
});
Give #chart and #grid a height in your page and that is the whole screen.
The same thing in React
The React adapter is a factory: you pass it React and createGrid, and it returns the component. The component forwards a ref whose .grid is the real grid, which is what the chart binds to.
import React, { useEffect, useRef } from 'react';
import { createGrid } from '@toclocoinc/lattice-grid';
import { createChart } from '@toclocoinc/lattice-grid/modules/charts';
import { createLatticeGrid } from '@toclocoinc/lattice-grid/modules/react';
import '@toclocoinc/lattice-grid/css';
const LatticeGrid = createLatticeGrid({ React, createGrid });
const columns = [
{ field: 'carrier', title: 'Carrier', filter: { type: 'set' } },
{ field: 'days', title: 'Delivery days', type: 'number' },
];
export function DeliveryTimes({ rows }) {
const gridRef = useRef(null);
const chartEl = useRef(null);
useEffect(() => {
const chart = createChart({
grid: gridRef.current.grid, container: chartEl.current,
type: 'boxplot', x: 'carrier', y: 'days', title: 'Delivery days by carrier',
});
return () => chart.destroy();
}, []);
return (
<>
<div ref={chartEl} style={{ height: 300 }} />
<LatticeGrid ref={gridRef} rowKey="id" columns={columns} rows={rows} style={{ height: 300 }} />
</>
);
}
Pass it the same thirty rows as the first listing: a carrier name and a number of days on each.
The options used
| Option | Type | What it does |
|---|---|---|
grid |
Grid | Required. The grid to read. |
container |
Element or string | Required. Where to draw. |
type |
string | 'boxplot' here. |
x |
string | The category column. Here, the carrier, so each gets its own box. |
y |
string | The measure column. Here, the delivery days summarised in each box. |
title |
string | Drawn above the plot. |
Go further
The charts page lists every chart type the same grid can feed, and the distribution family demo draws the box plot beside the histogram and the violin. To see how a chart keeps following the grid when you filter by clicking, read how to draw a chart that follows the grid.