Developer ToolsFree generatorPDF, Excel, Word export

Python Script Generator for X-bar R Charts and Cpk

You do not need a commercial SPC package to compute X-bar and R limits, Cpk and Ppk from a CSV export. This generator writes a short Python script that uses only the standard library, so it runs on any engineering PC or inside a data pipeline.

Fill in

Readings per subgroup, taken in time order

Generated code
Download:

spc_capability.py

import csv
import statistics

CSV_PATH = "bore_diameter.csv"
COLUMN = "diameter_mm"
N = 5
USL = 25.05
LSL = 24.95
LABEL = "Bore diameter (mm)"

# Shewhart constants by subgroup size
A2 = {2: 1.880, 3: 1.023, 4: 0.729, 5: 0.577, 6: 0.483, 7: 0.419, 8: 0.373, 9: 0.337, 10: 0.308}
D3 = {2: 0.0, 3: 0.0, 4: 0.0, 5: 0.0, 6: 0.0, 7: 0.076, 8: 0.136, 9: 0.184, 10: 0.223}
D4 = {2: 3.267, 3: 2.574, 4: 2.282, 5: 2.114, 6: 2.004, 7: 1.924, 8: 1.864, 9: 1.816, 10: 1.777}
D2 = {2: 1.128, 3: 1.693, 4: 2.059, 5: 2.326, 6: 2.534, 7: 2.704, 8: 2.847, 9: 2.970, 10: 3.078}

values = []
with open(CSV_PATH, newline="") as f:
    for row in csv.DictReader(f):
        if row[COLUMN].strip() != "":
            values.append(float(row[COLUMN]))

groups = [values[i:i + N] for i in range(0, len(values) - N + 1, N)]
if len(groups) < 20:
    print("Warning: only", len(groups), "subgroups; use 20 to 25 or more for stable limits")

xbars = [sum(g) / N for g in groups]
ranges = [max(g) - min(g) for g in groups]
xbarbar = sum(xbars) / len(xbars)
rbar = sum(ranges) / len(ranges)

ucl_x = xbarbar + A2[N] * rbar
lcl_x = xbarbar - A2[N] * rbar
ucl_r = D4[N] * rbar
lcl_r = D3[N] * rbar

sigma_within = rbar / D2[N]
mean_all = statistics.mean(values)
sigma_overall = statistics.stdev(values)

cp = (USL - LSL) / (6 * sigma_within)
cpk = min(USL - xbarbar, xbarbar - LSL) / (3 * sigma_within)
pp = (USL - LSL) / (6 * sigma_overall)
ppk = min(USL - mean_all, mean_all - LSL) / (3 * sigma_overall)

print(LABEL)
print("Subgroups:", len(groups), "Readings used:", len(groups) * N)
print("X-bar chart: LCL %.4f  CL %.4f  UCL %.4f" % (lcl_x, xbarbar, ucl_x))
print("R chart:     LCL %.4f  CL %.4f  UCL %.4f" % (lcl_r, rbar, ucl_r))
print("Sigma within %.5f  Sigma overall %.5f" % (sigma_within, sigma_overall))
print("Cp %.3f  Cpk %.3f  Pp %.3f  Ppk %.3f" % (cp, cpk, pp, ppk))

for i, (xb, r) in enumerate(zip(xbars, ranges), start=1):
    flags = []
    if xb > ucl_x or xb < lcl_x:
        flags.append("X-bar beyond limits")
    if r > ucl_r or r < lcl_r:
        flags.append("R beyond limits")
    if flags:
        print("Subgroup", i, "->", ", ".join(flags))

Uses only the Python standard library. Check that the data are in time order, that every subgroup is rational, and that the process is in statistical control on the X-bar and R charts before trusting Cp and Cpk. Pp and Ppk use the overall standard deviation of all readings used.

Feed SPC scripts from your ERP

Optional: help building a scheduled, read-only extract of inspection results into a capability report.

Optional. The tool and every export work without this. No spam.

How to use it

Enter the CSV path, the column with your readings and the subgroup size. Add the upper and lower specification limits. Copy the script, save it as spc_capability.py and run it with Python 3. Readings must be in time order because the script cuts them into consecutive subgroups of the size you set. The script prints the X-bar and R limits, Cp, Cpk, Pp, Ppk and any subgroup beyond the control limits.

  • Needs Python 3 only, no packages to install
  • Reads one numeric column, ignores blank cells
  • Warns when there are fewer than 20 subgroups

What the script calculates

Within-subgroup sigma is Rbar divided by d2, which describes short-term variation. Cp is the spec width over six of that sigma, and Cpk uses the distance from the process mean to the nearest limit over three sigma. Pp and Ppk use the overall sample standard deviation of all readings, which includes between-subgroup shifts, so they describe long-term performance. When Ppk is much lower than Cpk the process mean is wandering between subgroups.

Reading the output

First check the control charts. If the R chart shows points beyond the upper limit, the variation is not stable and the capability indices are not meaningful. If X-bar has out-of-limit points, find the assignable causes and rerun with corrected data or after the process is stabilized. Only then compare Cpk with the customer requirement, commonly 1.33 for existing processes and 1.67 for new ones, always using the value your customer or control plan specifies.

Common mistakes

Do not sort the data: sorting destroys the time order and the subgroups. Do not mix lots, machines or shifts inside one subgroup. Do not use the script for strongly non-normal data such as flatness or runout without checking the distribution, since the indices assume approximately normal data. Finally, keep the script and the data file together with a date so the analysis is reproducible during an audit.

Frequently Asked Questions

Why does the script use Rbar divided by d2?

It is the standard estimate of within-subgroup sigma for X-bar and R charts. The constant d2 depends on the subgroup size and converts the average range into an estimate of the standard deviation under normality.

What if my readings are not in subgroups?

Set the subgroup size to 2 and treat consecutive pairs as subgroups, or use an individuals and moving range chart. The SQL generator and chart selection guide cover individuals data.

Can I use more than 10 readings per subgroup?

This script supports sizes 2 to 10. For larger subgroups an X-bar and S chart is preferred, because the range is less efficient than the standard deviation for large samples.

Does a high Cpk guarantee no defects?

No. It estimates capability under the assumptions of statistical control and normality. Measurement error, non-normal data and process shifts can all produce defects even at a high Cpk, so confirm with observed data.

If your measurements live in an ERP or QMS database rather than a CSV, Netray can help build the read-only extract that feeds a script like this.