Lattice Grid

blog

Pareto Chart for Defect Causes

Building…
Loading a live grid…

You are a quality engineer, and you want to know which few causes are behind most of your defects. Ten causes, three shifts, a count for each: the table has every number, but the question is about priority. Where do you spend the next fix? A Pareto chart answers that at a glance. It ranks the causes by count, tallest first, and lays a cumulative share line over the bars, so the point where the line crosses eighty percent marks the vital few.

The live example starts with every shift counted together. The chart is bound to the grid, so it draws exactly the rows the grid is showing. Put the word night in the box, or open the filter on the Shift column, and the bars re-rank and the line redraws for that shift on the next frame.

Why a Pareto chart and not a bar chart

A plain bar chart ranks the causes but leaves you to add them up in your head. The Pareto adds a second axis, 0 to 100 percent, with the running total drawn on it, so how much of the problem the first three bars cover is read straight off the line instead of calculated.

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 cause and y the count to total for each one. Sort, filter or edit the grid and the chart follows, because a chart of rows you cannot see would be describing a different production line.

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 causes = [
  ['Solder bridge', [150, 140, 130]], ['Cold joint', [110, 100, 100]],
  ['Missing component', [90, 80, 70]], ['Misaligned part', [25, 20, 20]],
  ['Scratched casing', [18, 15, 12]], ['Loose screw', [15, 13, 12]],
  ['Label error', [10, 10, 10]], ['Cracked lens', [8, 6, 6]],
  ['Wrong polarity', [5, 5, 5]], ['Dust contamination', [5, 5, 5]],
];
const shifts = ['Early', 'Day', 'Night'];
const rows = causes.flatMap(([cause, counts], i) =>
  shifts.map((shift, j) => ({ id: i * 3 + j + 1, cause, shift, count: counts[j] })));

const grid = createGrid(document.querySelector('#grid'), {
  rowKey: 'id',
  columns: [
    { field: 'cause', title: 'Cause', filter: { type: 'set' } },
    { field: 'shift', title: 'Shift', filter: { type: 'set' } },
    { field: 'count', title: 'Defects', type: 'number' },
  ],
  rows,
});

createChart({
  grid, container: '#chart', type: 'pareto',
  x: 'cause', y: 'count', title: 'Defects by cause',
});

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: 'cause', title: 'Cause', filter: { type: 'set' } },
  { field: 'shift', title: 'Shift', filter: { type: 'set' } },
  { field: 'count', title: 'Defects', type: 'number' },
];

export function DefectCauses({ rows }) {
  const gridRef = useRef(null);
  const chartEl = useRef(null);

  useEffect(() => {
    const chart = createChart({
      grid: gridRef.current.grid, container: chartEl.current,
      type: 'pareto', x: 'cause', y: 'count', title: 'Defects by cause',
    });
    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, with cause, shift and count 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 'pareto' here.
x / y string Category and measure columns. Here, the cause and the count to total for each.
title string Drawn above the plot.

The line half of a Pareto also takes curve, which names how the cumulative line connects its readings, and emphasis and seriesStyle, which set its weight and dash.

Go further

The charts page lists every chart type the same grid can feed, and the cartesian family demo draws the Pareto beside the bar, line and combo types. To see how a chart keeps following the grid when you filter by clicking, read how to draw a chart that follows the grid.

Read next

  • Pie Chart of Revenue Share by Channel

    Bind a pie chart to a grid of revenue by channel: show each channel as a share of the quarter, and filter the rows to redraw the slices.

  • Heatmap of Sign-ups by Hour and Weekday

    Bind a heatmap to a grid of sign-ups: shade every weekday and hour by volume to time a campaign send, and filter the rows to redraw it.

  • Violin Chart of Salary Bands by Level

    Bind a violin chart to a grid of salaries: see the shape of pay at each level, including two bands inside one, and filter the rows to redraw it.

All posts RSS