Attribute Control Charts (p, np, c, u): Implementation and Factory Deployment
Attribute data represents discrete quality characteristics — pass/fail outcomes, defect counts, or nonconformities per inspection unit. Unlike the continuous measurements tracked on variable charts under SPC fundamentals and control chart taxonomy, attribute charts rest on distinct statistical foundations rooted in the binomial and Poisson distributions. Manufacturing operations deploy p, np, c, and u charts when measurement systems are impractical, inspection is destructive, or quality criteria are inherently categorical — final visual audit, supplier scorecards, and compliance-driven pass/fail gates.
What Breaks When the Wrong Attribute Chart Is Automated
The failure that dominates real deployments is fixed limits on variable sample sizes. A p-chart's control limits scale with $1/\sqrt{n_i}$, so when inspection lots swing from 200 units on one shift to 1,500 on the next, a chart drawn with a single frozen limit line cries wolf on every large lot and goes blind on every small one. The same trap sinks the u-chart. Automating this incorrectly does not merely add noise — it trains operators to ignore the chart entirely, defeating the point of statistical process control.
The second failure is distributional mismatch. Feeding count data into a variable-chart routine — the machinery behind an X-Bar R chart — produces 3σ limits calibrated to a normal assumption that count data never satisfies. Proportion-defective metrics follow the binomial distribution; defect-count metrics follow the Poisson. Their limits scale non-linearly with sample size and cannot be produced by the same code path. The error is silent until an auditor reconstructs the math.
The third is the zero-defect / near-zero trap. In high-yield modern lines where $\bar{p} \approx 0$ or $\bar{c} < 1$, the lower control limit collapses to zero and the upper limit becomes artificially tight, generating false alarms on any nonzero point. A pipeline that applies the naive 3σ formula in that regime is unusable without an exact-limits or attribute-CUSUM fallback.
Chart Selection and Statistical Foundations
The choice between p/np and c/u charts hinges on two operational factors: whether the metric tracks defectives (nonconforming units — a part is good or bad) or defects (nonconformities — a part may carry several), and whether the inspection sample size is constant.
| Chart | Metric | Sample size | Distribution | 3σ limit formula |
|---|---|---|---|---|
| p | Proportion defective | Variable | Binomial | $\bar{p} \pm 3\sqrt{\bar{p}(1-\bar{p})/n_i}$ |
| np | Count defective | Constant ($n$) | Binomial | $n\bar{p} \pm 3\sqrt{n\bar{p}(1-\bar{p})}$ |
| c | Count of defects | Constant | Poisson | $\bar{c} \pm 3\sqrt{\bar{c}}$ |
| u | Defects per unit | Variable | Poisson | $\bar{u} \pm 3\sqrt{\bar{u}/n_i}$ |
The centerline for a p-chart is the pooled proportion $\bar{p} = \frac{\sum d_i}{\sum n_i}$ — total defectives divided by total inspected units, not the simple mean of per-lot proportions. The u-chart mirrors this with $\bar{u} = \frac{\sum c_i}{\sum n_i}$. This pooling is what makes variable-$n$ limits correct, and it is mandated by the AIAG SPC Reference Manual and ISO 7870-2. The np-chart uses $\sigma = \sqrt{n\bar{p}(1-\bar{p})}$ and is only valid when every subgroup shares the same $n$; the c-chart's variance equals its mean, so $\sigma = \sqrt{\bar{c}}$.
When to Use an Attribute Chart vs. a Variable Chart
Attribute charts trade statistical power for cost. Because a pass/fail outcome carries far less information than a measured dimension, an attribute chart needs a much larger sample to detect the same shift. The decision is deterministic:
- Use a variable chart whenever continuous metrology is available and affordable. An X-Bar R chart for subgroups of 2–9, an X-Bar S chart once subgroups exceed nine, or an I-MR chart for single readings all detect small shifts earlier and with less data than any attribute equivalent.
- Use an attribute chart when measurement is destructive, when the characteristic is genuinely categorical (present/absent, conforming/nonconforming), when inspection is visual, or when you are aggregating many characteristics into a single go/no-go verdict at final audit or incoming inspection.
- Choose p vs np on sample-size stability: constant lot size → np (raw counts are easier for operators to read); fluctuating lot size → p.
- Choose c vs u on the inspection unit: a fixed inspection area or unit → c; a variable area or a per-part rate → u.
Once control is established on any of these, quantifying conformance to specification is the job of process capability analysis (Cp, Cpk, Pp, Ppk) — though capability indices apply to variable data, so an attribute stream is typically converted to a defect-rate or DPMO metric first.
Production-Ready Python Implementation
Factory data streams rarely arrive clean. MES systems output irregular timestamps, missing lot identifiers, and fluctuating inspection counts, so a robust attribute-chart engine must validate inputs, compute per-subgroup variable limits, and never propagate a silent NaN. The class below computes the center line, UCL, and LCL for all four chart families from a single interface.
import numpy as np
import pandas as pd
import warnings
from typing import Optional
class AttributeControlChart:
"""Production-grade engine for p, np, c, and u control charts.
Handles variable subgroup sizes, missing data, and the zero-defect
boundary. Center lines use pooled (weighted) proportions/rates so
variable-n limits stay correct, per AIAG SPC and ISO 7870-2.
"""
def __init__(self, chart_type: str, sigma: float = 3.0) -> None:
valid_types = {"p", "np", "c", "u"}
if chart_type.lower() not in valid_types:
raise ValueError(f"Unsupported chart type. Choose from {valid_types}.")
self.chart_type = chart_type.lower()
self.z = sigma
def calculate_limits(self, data: pd.DataFrame) -> pd.DataFrame:
"""Compute center line, UCL, and LCL for the selected chart.
Expected columns by chart type:
p: 'defectives', 'sample_size'
np: 'defectives', 'sample_size'
u: 'defects', 'sample_size'
c: 'defects'
"""
df = data.copy()
ct = self.chart_type
# --- Column validation + null pruning (fail loud, not silent) ---
if ct in {"p", "np"}:
required = {"defectives", "sample_size"}
if not required.issubset(df.columns):
raise ValueError(f"{ct}-chart requires {required} columns.")
df = df.dropna(subset=["defectives", "sample_size"])
elif ct == "u":
if not {"defects", "sample_size"}.issubset(df.columns):
raise ValueError("u-chart requires 'defects' and 'sample_size' columns.")
df = df.dropna(subset=["defects", "sample_size"])
elif ct == "c":
if "defects" not in df.columns:
raise ValueError("c-chart requires a 'defects' column.")
df = df.dropna(subset=["defects"])
if df.empty:
raise ValueError("No valid rows remain after dropping missing values.")
# --- Per-chart centerline + per-subgroup sigma ---
if ct == "p":
df["metric"] = df["defectives"] / df["sample_size"]
p_bar = df["defectives"].sum() / df["sample_size"].sum() # pooled
sigma = np.sqrt(p_bar * (1 - p_bar) / df["sample_size"])
center = p_bar
elif ct == "np":
if df["sample_size"].nunique() > 1:
warnings.warn(
"np-chart assumes constant sample size. Variable n "
"detected — use a p-chart instead."
)
n = df["sample_size"].iloc[0]
p_bar = df["defectives"].sum() / df["sample_size"].sum()
df["metric"] = df["defectives"]
center = n * p_bar
sigma = np.full(len(df), np.sqrt(n * p_bar * (1 - p_bar)))
elif ct == "u":
df["metric"] = df["defects"] / df["sample_size"]
u_bar = df["defects"].sum() / df["sample_size"].sum() # pooled
sigma = np.sqrt(u_bar / df["sample_size"])
center = u_bar
elif ct == "c":
df["metric"] = df["defects"]
center = df["metric"].mean()
sigma = np.full(len(df), np.sqrt(center))
df["center_line"] = center
df["ucl"] = center + self.z * sigma
# A probability/count limit can never fall below zero.
df["lcl"] = np.maximum(0.0, center - self.z * sigma)
return df[["metric", "center_line", "ucl", "lcl"]]
For p and u charts the UCL and LCL are vectors — one value per subgroup — because $\sigma$ depends on $n_i$. Rendering those step-wise limit bands, rather than a single flat line, is handled downstream by the dynamic Plotly control chart renderer, and freezing versus recomputing them across a production run is the concern of rolling-window limit recalibration.
Validation and Testing
Before this engine is allowed to raise an alert, verify it against a small set of contracts:
- Pooled centerline check. On a fixture with deliberately uneven lot sizes, assert the p-chart center equals $\sum d_i / \sum n_i$ and not the mean of per-lot rates — the two differ whenever $n$ varies, and only the pooled value is correct.
- Variable-limit monotonicity. Assert that for a p- or u-chart, the subgroup with the largest $n_i$ has the tightest (narrowest) limits and the smallest $n_i$ the widest. A flat limit line across variable $n$ is the classic bug.
- Zero-floor clamp. Feed a subgroup where $\bar{p} - 3\sigma < 0$ and assert
lcl == 0.0exactly. - np constant-n guard. Pass variable
sample_sizeto the np path and assert the warning fires; np limits are invalid otherwise. - Minimum data. AIAG guidance calls for at least 20–25 subgroups of verified-stable data before limits are frozen for Phase II monitoring; with fewer, $\bar{p}$ or $\bar{c}$ is too volatile to anchor the baseline.
Attribute charting has no Gage R&R prerequisite in the variable-data sense, but the attribute agreement analysis (appraiser-to-standard and appraiser-to-appraiser kappa) is its measurement-system-analysis equivalent and must pass before visual-inspection counts are trusted as chart input.
Failure Modes and Edge Cases
| Symptom | Root cause | Fix |
|---|---|---|
| Chart alarms on every large lot | Fixed limits applied to variable $n$ | Compute per-subgroup $\sigma = \sqrt{\bar{p}(1-\bar{p})/n_i}$; draw step-wise limit bands |
| LCL sits at zero, UCL feels too tight | High-yield regime ($\bar{p}\approx0$ or $\bar{c}<1$) | Switch to exact binomial/Poisson limits or an attribute CUSUM/EWMA for micro-shifts |
| More out-of-control points than expected, no assignable cause | Overdispersion — real variance exceeds the binomial/Poisson model | Chi-square goodness-of-fit test; if it fails, investigate batch-to-batch heterogeneity before widening limits |
| Centerline drifts when lot sizes change | Simple mean of per-lot rates used instead of pooled | Use $\bar{p}=\sum d_i/\sum n_i$ (and $\bar{u}=\sum c_i/\sum n_i$) |
| Silent gaps in the chart | NaN defective/defect counts propagated |
Validate columns and dropna before computation, as the engine does |
| np limits look wrong after a lot-size change | np used on a process whose $n$ is not actually constant | Migrate to a p-chart; np is only valid at fixed $n$ |
Overdispersion deserves emphasis because it is the subtle one. Attribute data from real production often shows greater variance than the theoretical model predicts, usually because defects cluster within batches or share a common cause. Widening the limits to swallow the extra variance hides the very heterogeneity an engineer should be chasing; the correct response is a goodness-of-fit test and a root-cause investigation, not a looser chart.
Timestamp drift and missing lot identifiers upstream corrupt subgroup boundaries before any of this math runs — align records first with the time-series alignment pipeline, and validate incoming batches against a schema through batch data validation and error handling.
Signal Interpretation and Run Rules
Attribute charts follow the same Western Electric and Nelson run rules as variable charts, evaluated in the automated control chart generation and calculation layer, but with two caveats. First, the discrete nature of binomial and Poisson data creates ladder effects: points can only land on specific values, so zone-based rules that assume a continuous distribution behave differently near the limits. Second, when limits are narrow this granularity can inflate the Type I (false-alarm) rate. For processes where continuous measurement is feasible and small shifts must be caught early, an X-Bar S chart for large subgroups captures within-subgroup variation far more sensitively than any attribute count allows.
Authoritative derivations for attribute control limits, overdispersion diagnostics, and chi-square testing are documented in the NIST Engineering Statistics Handbook: Control Charts for Attributes.
Compliance Notes
- AIAG SPC Reference Manual (2nd ed.) — specifies pooled centerlines for variable-sample-size p and u charts and the 20–25 subgroup minimum for establishing Phase I limits; the engine's weighted centerline and the validation checklist are the artifacts that demonstrate conformance.
- ISO 7870-2 — defines the Shewhart control-chart limit formulas for p, np, c, and u charts and the constant-$n$ requirement for np and c; cite the clause when justifying chart selection to an auditor.
- ISO 9001:2015, Clause 9.1.1 — requires monitoring and measurement of process performance; a traceable attribute chart with documented limits satisfies the evidence requirement for a categorical characteristic.
- NIST Engineering Statistics Handbook, Section 6.3.3 — treats the zero-defect boundary and exact-limit alternatives; reference it when documenting a high-yield fallback away from the 3σ approximation.
Frequently Asked Questions
How do I handle variable subgroup sizes on a p-chart?
Compute the limits per subgroup. The p-chart center line is the pooled proportion $\bar{p}=\sum d_i/\sum n_i$, but the spread term $\sigma_i=\sqrt{\bar{p}(1-\bar{p})/n_i}$ depends on each lot's own $n_i$, so the UCL and LCL are vectors that step in and out as the sample size changes. Drawing a single flat limit line across variable $n$ is the most common attribute-charting bug — it over-alarms on large lots and under-alarms on small ones.
When should I use a c-chart versus a u-chart?
Both count defects (nonconformities), and both are Poisson-based; the difference is the inspection unit. Use a c-chart when the area of opportunity is constant — the same fixed panel, the same length of weld, the same board every time — and plot the raw defect count. Use a u-chart when the inspection area varies from unit to unit and you must normalize to defects per unit, which makes the limits vary with $n_i$ exactly as on a p-chart.
Why does my LCL keep sitting at zero?
Because a proportion or a count cannot be negative, the lower limit is clamped to zero whenever $\bar{p}-3\sigma$ (or $\bar{c}-3\sqrt{\bar{c}}$) would go below it. In a high-yield process where $\bar{p}\approx0$ or $\bar{c}<1$ this is expected behaviour, not a defect. It does mean the chart cannot signal an improvement (a downward shift), so if catching yield gains matters, switch to exact Poisson/binomial limits or an attribute CUSUM/EWMA that is sensitive to small downward shifts.
My chart shows too many out-of-control points with no assignable cause — what now?
Test for overdispersion before touching the limits. Real attribute data frequently carries more variance than the binomial or Poisson model assumes, usually because defects cluster within batches or share a common cause. Run a chi-square goodness-of-fit test; if the data is overdispersed, the excess points are telling you about batch-to-batch heterogeneity that deserves investigation. Simply widening the limits to absorb the variance hides the signal the chart exists to surface.
Can I use an attribute chart instead of a variable chart to save on gauging?
You can, but expect to pay for it in sample size. A pass/fail outcome carries far less information than a measured dimension, so an attribute chart needs a substantially larger sample to detect the same shift with the same power. When affordable metrology exists, a variable chart — X-Bar R, X-Bar S, or I-MR — detects small process shifts earlier and with less data. Reserve attribute charts for destructive, visual, or genuinely categorical inspection.
Related
- X-Bar R chart implementation — small-subgroup variable monitoring when metrology is available
- X-Bar S chart for large subgroups — unbiased dispersion when subgroups exceed nine
- Individual Moving Range (I-MR) charts — single-observation monitoring for low-volume processes
- Process capability analysis (Cp, Cpk, Pp, Ppk) — quantifying conformance once control is established
- Automated control chart generation and calculation — evaluating out-of-control signals against Nelson and Western Electric run rules
For chart selection criteria across every data type, see SPC Fundamentals & Control Chart Taxonomy.