ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.
WHITEPAPER

Statistical Process Control: Charts & Methods

Updated October 2026

Published: December 27, 2025 | Reading time: 9 minutes

Executive Summary

Statistical process control (SPC) uses control charts to separate ordinary variation in a process from signals that something has changed. The charts differ in what they detect quickly: Shewhart charts react to large shifts, while CUSUM and EWMA charts accumulate evidence and react faster to small, sustained shifts.

This paper is a method guide. It explains the charts, how to set them up and where they mislead. The only numbers in it come from a simulation in section 4, whose code is shown; they describe that simulated setup and are not a claim about any plant, hospital or company.

To check whether your own process is stable and can hold its specification, try the free control chart tool.

Key Points

  • Small shifts are slow to show on a Shewhart chart. In the simulation a 1 standard deviation shift took 44 points on average to trigger a 3-sigma chart, against about 10 for EWMA and CUSUM tuned to the same false-alarm rate.
  • Large shifts need no help. For a 3 standard deviation shift all three charts alarmed within about two to three points.
  • Correlated data break the independence assumption. With correlation 0.6 between consecutive points, EWMA and CUSUM false alarms came roughly nine times as often (every 38 to 41 points against every 350 to 370).
  • Smaller EWMA weights mean longer memory. A small smoothing weight lets older points count for more and suits small shifts; a large weight behaves more like a Shewhart chart.

Recommendation: establish that the process is stable before monitoring it, choose the chart to match the shift you care about, and check autocorrelation before trusting the limits.

1. Introduction

1.1 The Problem

Every process varies. The question a control chart answers is whether today's variation is the process's normal pattern (common cause) or evidence of a change (special cause). Reacting to noise wastes effort and can make a process worse; missing a real shift lets defects or losses accumulate.

1.2 What This Paper Covers

  • Shewhart, CUSUM and EWMA charts and what each is good at
  • Setting up a chart: a stable baseline, then monitoring
  • A reproducible simulation of detection speed and false alarms, including correlated data
  • Guidance for choosing and checking a chart

2. Background

2.1 Shewhart Charts

A Shewhart chart plots each point against limits at the center line plus and minus three standard deviations of the plotted statistic. With independent, approximately normal data, a point beyond the limits occurs about 0.27% of the time when nothing has changed, so false alarms arrive on average every 370 points. The chart is simple and reacts quickly to large shifts, but it uses only the latest point and is slow on small shifts unless extra run rules are added.

2.2 CUSUM Charts

A CUSUM chart accumulates deviations from a target. For an upward shift it tracks St = max(0, St-1 + xt - k) in standard units, where k, often half the shift to detect, is the allowance, and signals when St exceeds a decision limit h. A mirror-image sum tracks downward shifts. Small, persistent shifts build up and trigger a signal sooner than a single-point rule would.

2.3 EWMA Charts

An EWMA chart plots zt = lambda * xt + (1 - lambda) * zt-1, with limits at the center line plus and minus L times the standard deviation times the square root of lambda / (2 - lambda) (the long-run value). A small lambda gives the newest point little weight and averages over a long history, which suits small shifts; lambda = 1 reduces to a Shewhart chart.

3. Approach

3.1 Phase I and Phase II

In Phase I, collect baseline data, look for special causes in it, remove those points once their causes are understood, and estimate the center line and spread from what remains. In Phase II, monitor new data against those limits. Limits computed from a baseline that includes unstable periods are wrong in both directions.

3.2 Choosing a Chart

Choose by the size of shift that matters. For large shifts a Shewhart chart is enough; for shifts of about one standard deviation or less, CUSUM or EWMA tuned for that shift detect faster for the same false-alarm rate. Set the parameters (k and h, or lambda and L) so that the in-control average run length is acceptable, and check it by simulation if you change them.

3.3 Autocorrelation

Control limits assume independent observations. Consecutive measurements from slow processes, or averages over overlapping windows, are often positively correlated, which makes EWMA and CUSUM signal far too often. Check the autocorrelation of the baseline; if it is material, model it (for example fit an autoregressive model and chart the residuals) or widen the limits.

3.4 Capability

Capability indices such as Cp and Cpk compare the process spread with the specification limits, and only mean something when the process is stable and roughly normal. Report them together with the evidence of stability, not in its place.

4. A Reproducible Simulation

The simulation runs three charts on standardized data (target 0, standard deviation 1): a 3-sigma Shewhart chart, an EWMA chart with lambda = 0.2 and L = 2.86, and a two-sided CUSUM with k = 0.5 and h = 4.77. For each mean shift it measures the average run length, the number of points until the first alarm, over 3,000 runs. The parameters were chosen to give an in-control run length near 370, the Shewhart value.

import numpy as np

T, REPS = 4000, 3000        # time steps per run (an alarm almost surely occurs before this) and runs per setting
LAM, L = 0.2, 2.86          # EWMA smoothing weight and control-limit width
K, H = 0.5, 4.77            # CUSUM reference value and decision limit, in standard deviations

def run_lengths(shift, phi=0.0, seed=1):
    """Average run length (steps until the first alarm) for three charts on standardized data."""
    rng = np.random.default_rng(seed)
    e = rng.normal(size=(T, REPS)) * np.sqrt(1 - phi ** 2)      # keeps the marginal sd at 1 when phi > 0
    x = np.empty((T, REPS)); x[0] = rng.normal(size=REPS)
    for t in range(1, T):
        x[t] = phi * x[t - 1] + e[t]
    x += shift
    ewma_lim = L * np.sqrt(LAM / (2 - LAM))
    z = np.zeros(REPS); hi = np.zeros(REPS); lo = np.zeros(REPS)
    first = {"Shewhart": np.full(REPS, T), "EWMA": np.full(REPS, T), "CUSUM": np.full(REPS, T)}
    for t in range(T):
        z = LAM * x[t] + (1 - LAM) * z
        hi = np.maximum(0, hi + x[t] - K); lo = np.maximum(0, lo - x[t] - K)
        alarms = {"Shewhart": np.abs(x[t]) > 3, "EWMA": np.abs(z) > ewma_lim, "CUSUM": (hi > H) | (lo > H)}
        for name, a in alarms.items():
            first[name] = np.where(a & (first[name] == T), t + 1, first[name])
    return {name: f.mean() for name, f in first.items()}

print("average run length (steps to first alarm); independent data")
print(f"{'mean shift':>10s} {'Shewhart':>10s} {'EWMA':>8s} {'CUSUM':>8s}")
for shift in (0.0, 0.5, 1.0, 2.0, 3.0):
    r = run_lengths(shift)
    print(f"{shift:>8.1f} sd {r['Shewhart']:10.1f} {r['EWMA']:8.1f} {r['CUSUM']:8.1f}")

Output:

average run length (steps to first alarm); independent data
mean shift   Shewhart     EWMA    CUSUM
     0.0 sd      356.5    373.7    363.4
     0.5 sd      154.2     36.9     36.4
     1.0 sd       44.0     10.0     10.2
     2.0 sd        6.5      3.6      3.9
     3.0 sd        2.0      2.3      2.5

With no shift, all three charts raised a false alarm about once in 360 to 375 points. For a 0.5 standard deviation shift EWMA and CUSUM needed about 37 points against 154 for Shewhart, and for a 1 standard deviation shift about 10 against 44. At a 3 standard deviation shift the charts were equivalent, within about half a point.

4.1 When Consecutive Points Are Correlated

The second block reuses the function above with no real shift but with each point correlated with the previous one (a first-order autoregressive process, phi being the correlation, with the overall standard deviation still 1).

# Same charts, no real shift, but each point is correlated with the one before it (AR(1), marginal sd still 1).
# This block reuses run_lengths from the previous block.
print("in-control average run length when consecutive points are correlated")
print(f"{'phi':>5s} {'Shewhart':>10s} {'EWMA':>8s} {'CUSUM':>8s}")
for phi in (0.0, 0.3, 0.6):
    r = run_lengths(0.0, phi=phi, seed=5)
    print(f"{phi:5.1f} {r['Shewhart']:10.1f} {r['EWMA']:8.1f} {r['CUSUM']:8.1f}")
in-control average run length when consecutive points are correlated
  phi   Shewhart     EWMA    CUSUM
  0.0      376.1    352.5    366.0
  0.3      365.1     94.0     85.7
  0.6      419.2     40.6     37.6

The Shewhart chart's false-alarm rate was unaffected here because each point's own distribution is unchanged (alarms cluster instead). EWMA and CUSUM, which add points up, signaled many times too often. This is one design; other chart settings and correlation structures give different numbers.

5. Practical Guidance

Point 1: Establish Stability First

Plot the baseline, look for special causes, and fix or exclude them before computing limits. Monitoring against limits from an unstable baseline produces false confidence.

Point 2: Match the Chart to the Shift That Matters

Decide the smallest shift worth detecting, then choose a chart and settings that detect it with an acceptable false-alarm interval. State the in-control run length you designed for.

Point 3: Check for Autocorrelation

Compute the autocorrelation of the baseline. If it is material, use a model-based chart or adjusted limits before using EWMA or CUSUM.

Point 4: Have a Response Plan

A signal is a prompt to investigate. Decide in advance who investigates, what is checked, and how a confirmed shift is handled, and record outcomes so false alarms and misses can be counted over time.

Point 5: Review the Limits Periodically

After a deliberate process change, recompute the baseline and limits. Limits left from the old process will signal constantly or not at all.

6. Conclusion

Control charts are only as useful as their assumptions are true. A Shewhart chart is a good default for large shifts, EWMA and CUSUM detect small ones sooner, and all of them need a stable baseline and, where data are correlated, adjustment for it. The simulation here shows the trade in detection speed and the cost of ignoring autocorrelation; test your own settings the same way before relying on them.

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai

Frequently Asked Questions

What is a control chart?

A time-ordered plot of a process measure with limits that mark its ordinary variation, used to tell normal variation from signals of change.

When should I use CUSUM or EWMA instead of a Shewhart chart?

When the shift you want to catch is small, about one standard deviation or less. They accumulate evidence and detect such shifts sooner for the same false-alarm rate, while a Shewhart chart is enough for large shifts.

What does the EWMA smoothing weight do?

A small weight averages over many past points and suits small shifts; a large weight gives the latest point more influence, and a weight of 1 is a Shewhart chart.

Why do my charts signal too often?

Common causes are limits estimated from an unstable baseline and positive autocorrelation between consecutive points. Check both before adjusting the chart.

What is average run length?

The average number of points until a chart signals. In control it measures the false-alarm interval; after a shift it measures detection speed.

References & Further Reading

  • Montgomery, D. C. (2019). Introduction to Statistical Quality Control (8th ed.). Wiley.
  • Page, E. S. (1954). Continuous inspection schemes. Biometrika, 41(1-2), 100-115.
  • Roberts, S. W. (1959). Control chart tests based on geometric moving averages. Technometrics, 1(3), 239-250.
  • Lucas, J. M., & Saccucci, M. S. (1990). Exponentially weighted moving average control schemes: properties and enhancements. Technometrics, 32(1), 1-12.