A Pareto chart combining descending-sorted bars (by frequency or count) with a cumulative percentage line overlay on a secondary y-axis. This visualization helps identify the most significant factors in a dataset by applying the Pareto principle (80/20 rule), making it one of the "7 Basic Tools of Quality" in Six Sigma and quality management. It reveals which categories contribute the most to an overall effect, enabling data-driven prioritization.

""" anyplot.ai
bar-pareto: Pareto Chart with Cumulative Line
Library: plotly 6.8.0 | Python 3.13.14
Quality: 90/100 | Updated: 2026-06-20
"""
import os
import numpy as np
import plotly.graph_objects as go
# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
GRID = "rgba(26,26,23,0.15)" if THEME == "light" else "rgba(240,239,232,0.15)"
# Imprint categorical palette
BRAND = "#009E73" # position 1 — Vital Few bars
BLUE = "#4467A3" # position 3 — cumulative line
# Data — manufacturing defect types (Pareto principle applied to quality control)
categories = [
"Scratches",
"Dents",
"Misalignment",
"Cracks",
"Discoloration",
"Burrs",
"Warping",
"Contamination",
"Chipping",
"Porosity",
]
counts = np.array([142, 118, 87, 64, 53, 38, 29, 21, 15, 9])
sort_idx = np.argsort(-counts)
categories = [categories[i] for i in sort_idx]
counts = counts[sort_idx]
cumulative_pct = np.cumsum(counts) / counts.sum() * 100
threshold_idx = int(np.searchsorted(cumulative_pct, 80, side="right")) + 1
# Plot
fig = go.Figure()
# Vital Few bars (Imprint brand green — categories driving 80% of defects)
fig.add_trace(
go.Bar(
x=categories[:threshold_idx],
y=counts[:threshold_idx],
marker={"color": BRAND, "line": {"width": 0}},
name="Vital Few",
yaxis="y",
)
)
# Trivial Many bars (muted — lower-priority defect categories)
fig.add_trace(
go.Bar(
x=categories[threshold_idx:],
y=counts[threshold_idx:],
marker={"color": INK_MUTED, "line": {"width": 0}},
name="Trivial Many",
yaxis="y",
)
)
# Cumulative percentage line (Imprint blue)
fig.add_trace(
go.Scatter(
x=categories,
y=cumulative_pct,
mode="lines+markers+text",
marker={"size": 14, "color": BLUE, "line": {"width": 2.5, "color": PAGE_BG}},
line={"width": 3.5, "color": BLUE, "shape": "linear"},
text=[f"{v:.0f}%" if i == threshold_idx - 1 else "" for i, v in enumerate(cumulative_pct)],
textposition="top center",
textfont={"size": 12, "color": BLUE},
name="Cumulative %",
yaxis="y2",
)
)
# 80% reference line
fig.add_hline(y=80, line={"color": INK_SOFT, "width": 2, "dash": "dot"}, yref="y2")
fig.add_annotation(
x=0.99,
y=80,
xref="paper",
yref="y2",
text="<b>80% threshold</b>",
showarrow=False,
font={"size": 12, "color": INK_SOFT},
xanchor="right",
yanchor="bottom",
yshift=6,
)
# Vital few region shading (subtle green tint)
fig.add_vrect(x0=-0.5, x1=threshold_idx - 0.5, fillcolor="rgba(0,158,115,0.06)", line_width=0, layer="below")
# Value labels on top 3 bars
for i in range(min(3, len(counts))):
fig.add_annotation(
x=categories[i],
y=counts[i],
text=f"<b>{counts[i]}</b>",
showarrow=False,
font={"size": 12, "color": BRAND},
yshift=12,
)
title = "bar-pareto · python · plotly · anyplot.ai"
# Style
fig.update_layout(
autosize=False,
title={"text": title, "font": {"size": 16, "color": INK}, "x": 0.5, "xanchor": "center", "y": 0.97},
xaxis={
"title": {"text": "Defect Type", "font": {"size": 12, "color": INK}, "standoff": 15},
"tickfont": {"size": 10, "color": INK_SOFT},
"showline": False,
"showgrid": False,
},
yaxis={
"title": {"text": "Frequency", "font": {"size": 12, "color": INK}, "standoff": 10},
"tickfont": {"size": 10, "color": INK_SOFT},
"showgrid": True,
"gridcolor": GRID,
"gridwidth": 1,
"zeroline": False,
"showline": False,
},
yaxis2={
"title": {"text": "Cumulative Percentage (%)", "font": {"size": 12, "color": INK}, "standoff": 10},
"tickfont": {"size": 10, "color": INK_SOFT},
"overlaying": "y",
"side": "right",
"range": [0, 108],
"showgrid": False,
"ticksuffix": "%",
"zeroline": False,
"linecolor": INK_SOFT,
},
legend={
"font": {"size": 10, "color": INK_SOFT},
"x": 0.68,
"y": 0.35,
"bgcolor": ELEVATED_BG,
"bordercolor": INK_SOFT,
"borderwidth": 1,
},
bargap=0.12,
paper_bgcolor=PAGE_BG,
plot_bgcolor=PAGE_BG,
font={"color": INK},
margin={"t": 80, "b": 60, "l": 80, "r": 90},
barmode="overlay",
)
# Save
fig.write_image(f"plot-{THEME}.png", width=800, height=450, scale=4)
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")
Part of Pareto Chart with Cumulative Line on anyplot.ai.