目录
-
- 摘要
- 一、SPC概述
-
- [1.1 什么是SPC](#1.1 什么是SPC)
- [1.2 控制图类型](#1.2 控制图类型)
- [1.3 控制限](#1.3 控制限)
- 二、数据准备
-
- [2.1 质量数据表](#2.1 质量数据表)
- [2.2 分布式存储](#2.2 分布式存储)
- 三、控制图计算
-
- [3.1 X-bar R控制图](#3.1 X-bar R控制图)
- [3.2 P控制图](#3.2 P控制图)
- 四、过程能力分析
-
- [4.1 过程能力指数](#4.1 过程能力指数)
- [4.2 过程能力评价](#4.2 过程能力评价)
- 五、异常检测
-
- [5.1 控制图规则](#5.1 控制图规则)
- [5.2 实时异常检测](#5.2 实时异常检测)
- 六、质量告警
-
- [6.1 SPC告警规则](#6.1 SPC告警规则)
- 七、实战案例
-
- [7.1 完整SPC监控系统](#7.1 完整SPC监控系统)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB质量实时监控技术。从SPC原理到控制图绘制,从过程能力分析到异常检测,从质量告警到持续改进,全面介绍SPC统计过程控制的核心方法。通过丰富的代码示例,帮助读者掌握质量实时监控的核心技能。
一、SPC概述
1.1 什么是SPC
SPC(Statistical Process Control)统计过程控制是一种质量控制方法:
#mermaid-svg-mx6WEyzkog9eCVUN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mx6WEyzkog9eCVUN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mx6WEyzkog9eCVUN .error-icon{fill:#552222;}#mermaid-svg-mx6WEyzkog9eCVUN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mx6WEyzkog9eCVUN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mx6WEyzkog9eCVUN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mx6WEyzkog9eCVUN .marker.cross{stroke:#333333;}#mermaid-svg-mx6WEyzkog9eCVUN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mx6WEyzkog9eCVUN p{margin:0;}#mermaid-svg-mx6WEyzkog9eCVUN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mx6WEyzkog9eCVUN .cluster-label text{fill:#333;}#mermaid-svg-mx6WEyzkog9eCVUN .cluster-label span{color:#333;}#mermaid-svg-mx6WEyzkog9eCVUN .cluster-label span p{background-color:transparent;}#mermaid-svg-mx6WEyzkog9eCVUN .label text,#mermaid-svg-mx6WEyzkog9eCVUN span{fill:#333;color:#333;}#mermaid-svg-mx6WEyzkog9eCVUN .node rect,#mermaid-svg-mx6WEyzkog9eCVUN .node circle,#mermaid-svg-mx6WEyzkog9eCVUN .node ellipse,#mermaid-svg-mx6WEyzkog9eCVUN .node polygon,#mermaid-svg-mx6WEyzkog9eCVUN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mx6WEyzkog9eCVUN .rough-node .label text,#mermaid-svg-mx6WEyzkog9eCVUN .node .label text,#mermaid-svg-mx6WEyzkog9eCVUN .image-shape .label,#mermaid-svg-mx6WEyzkog9eCVUN .icon-shape .label{text-anchor:middle;}#mermaid-svg-mx6WEyzkog9eCVUN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mx6WEyzkog9eCVUN .rough-node .label,#mermaid-svg-mx6WEyzkog9eCVUN .node .label,#mermaid-svg-mx6WEyzkog9eCVUN .image-shape .label,#mermaid-svg-mx6WEyzkog9eCVUN .icon-shape .label{text-align:center;}#mermaid-svg-mx6WEyzkog9eCVUN .node.clickable{cursor:pointer;}#mermaid-svg-mx6WEyzkog9eCVUN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mx6WEyzkog9eCVUN .arrowheadPath{fill:#333333;}#mermaid-svg-mx6WEyzkog9eCVUN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mx6WEyzkog9eCVUN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mx6WEyzkog9eCVUN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mx6WEyzkog9eCVUN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mx6WEyzkog9eCVUN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mx6WEyzkog9eCVUN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mx6WEyzkog9eCVUN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mx6WEyzkog9eCVUN .cluster text{fill:#333;}#mermaid-svg-mx6WEyzkog9eCVUN .cluster span{color:#333;}#mermaid-svg-mx6WEyzkog9eCVUN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mx6WEyzkog9eCVUN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mx6WEyzkog9eCVUN rect.text{fill:none;stroke-width:0;}#mermaid-svg-mx6WEyzkog9eCVUN .icon-shape,#mermaid-svg-mx6WEyzkog9eCVUN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mx6WEyzkog9eCVUN .icon-shape p,#mermaid-svg-mx6WEyzkog9eCVUN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mx6WEyzkog9eCVUN .icon-shape .label rect,#mermaid-svg-mx6WEyzkog9eCVUN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mx6WEyzkog9eCVUN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mx6WEyzkog9eCVUN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mx6WEyzkog9eCVUN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SPC控制
数据采集
统计分析
控制图
异常检测
过程改进
1.2 控制图类型
| 控制图 | 数据类型 | 说明 |
|---|---|---|
| X-bar R图 | 计量值 | 均值-极差图 |
| X-bar S图 | 计量值 | 均值-标准差图 |
| P图 | 计数值 | 不合格率图 |
| C图 | 计数值 | 缺陷数图 |
1.3 控制限
| 控制限 | 公式 | 说明 |
|---|---|---|
| UCL | μ + 3σ | 上控制限 |
| CL | μ | 中心线 |
| LCL | μ - 3σ | 下控制限 |
二、数据准备
2.1 质量数据表
python
// 质量数据表
share streamTable(100000:0,
`product_id`device_id`timestamp`measurement`spec_min`spec_max,
[SYMBOL, SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as quality_stream
// 启用持久化
enableTablePersistence(quality_stream, true, true, 1000000)
2.2 分布式存储
python
// 创建分布式表
db = database("dfs://quality_db", VALUE, 1..100)
schema = table(1:0,
`product_id`device_id`timestamp`measurement`spec_min`spec_max,
[SYMBOL, SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `quality_data, `device_id)
// 订阅写入
subscribeTable(, "quality_stream", "persist", -1,
def(msg) {
loadTable("dfs://quality_db", "quality_data").append!(msg)
}, 10000, 5000)
三、控制图计算
3.1 X-bar R控制图
python
// X-bar R控制图计算
def calculateXbarRChart(deviceId, subgroupSize = 5) {
// 获取数据
data = select measurement
from quality_stream
where device_id = deviceId
order by timestamp
// 分组
n = data.rows()
groupCount = n / subgroupSize
// 计算各组均值和极差
xbar = array(DOUBLE, 0)
r = array(DOUBLE, 0)
for (i in 0..groupCount) {
start = i * subgroupSize
end = (i + 1) * subgroupSize - 1
groupData = data.measurement[start:end]
xbar.append!(avg(groupData))
r.append!(max(groupData) - min(groupData))
}
// 计算控制限
xbarMean = avg(xbar)
rMean = avg(r)
// X-bar控制限(A2因子)
A2 = 0.577 // n=5时的A2值
UCL_xbar = xbarMean + A2 * rMean
LCL_xbar = xbarMean - A2 * rMean
// R控制限(D3, D4因子)
D3 = 0 // n=5时的D3值
D4 = 2.114 // n=5时的D4值
UCL_r = D4 * rMean
LCL_r = D3 * rMean
return dict(STRING, ANY, [
["xbar", xbar],
["r", r],
["xbarMean", xbarMean],
["rMean", rMean],
["UCL_xbar", UCL_xbar],
["LCL_xbar", LCL_xbar],
["UCL_r", UCL_r],
["LCL_r", LCL_r]
])
}
3.2 P控制图
python
// P控制图(不合格率)
def calculatePChart(deviceId, subgroupSize = 100) {
// 获取数据
data = select measurement, spec_min, spec_max
from quality_stream
where device_id = deviceId
order by timestamp
// 判断合格
data[`qualified] = data.measurement >= data.spec_min and data.measurement <= data.spec_max
// 分组计算不合格率
n = data.rows()
groupCount = n / subgroupSize
p = array(DOUBLE, 0)
for (i in 0..groupCount) {
start = i * subgroupSize
end = (i + 1) * subgroupSize - 1
groupData = data[start:end]
defectCount = sum(not groupData.qualified)
p.append!(defectCount * 1.0 / subgroupSize)
}
// 计算控制限
pMean = avg(p)
UCL = pMean + 3 * sqrt(pMean * (1 - pMean) / subgroupSize)
LCL = max(0, pMean - 3 * sqrt(pMean * (1 - pMean) / subgroupSize))
return dict(STRING, ANY, [
["p", p],
["pMean", pMean],
["UCL", UCL],
["LCL", LCL]
])
}
四、过程能力分析
4.1 过程能力指数
python
// 过程能力指数计算
def calculateProcessCapability(deviceId) {
// 获取数据
data = select measurement, spec_min, spec_max
from quality_stream
where device_id = deviceId
// 计算统计量
mean = avg(data.measurement)
std = std(data.measurement)
USL = avg(data.spec_max)
LSL = avg(data.spec_min)
// Cp指数
Cp = (USL - LSL) / (6 * std)
// Cpk指数
Cpu = (USL - mean) / (3 * std)
Cpl = (mean - LSL) / (3 * std)
Cpk = min(Cpu, Cpl)
// Pp指数
Pp = (USL - LSL) / (6 * std)
// Ppk指数
Ppu = (USL - mean) / (3 * std)
Ppl = (mean - LSL) / (3 * std)
Ppk = min(Ppu, Ppl)
return dict(STRING, ANY, [
["mean", mean],
["std", std],
["Cp", Cp],
["Cpk", Cpk],
["Pp", Pp],
["Ppk", Ppk]
])
}
4.2 过程能力评价
python
// 过程能力评价
def evaluateProcessCapability(Cpk) {
if (Cpk >= 1.67) {
return "优秀"
} else if (Cpk >= 1.33) {
return "良好"
} else if (Cpk >= 1.0) {
return "合格"
} else if (Cpk >= 0.67) {
return "不足"
} else {
return "严重不足"
}
}
五、异常检测
5.1 控制图规则
python
// Western Electric规则检测
def detectAnomalies(deviceId) {
chart = calculateXbarRChart(deviceId)
xbar = chart["xbar"]
UCL = chart["UCL_xbar"]
LCL = chart["LCL_xbar"]
CL = chart["xbarMean"]
anomalies = array(STRING, 0)
// 规则1:超出控制限
for (i in 0..xbar.size()) {
if (xbar[i] > UCL or xbar[i] < LCL) {
anomalies.append!("点" + string(i) + "超出控制限")
}
}
// 规则2:连续7点在中心线一侧
for (i in 0..xbar.size() - 7) {
above = sum(xbar[i:i+7] > CL)
below = sum(xbar[i:i+7] < CL)
if (above == 7 or below == 7) {
anomalies.append!("点" + string(i) + "-" + string(i+6) + "连续7点在中心线一侧")
}
}
// 规则3:连续6点递增或递减
for (i in 0..xbar.size() - 6) {
increasing = true
decreasing = true
for (j in 0..5) {
if (xbar[i+j] >= xbar[i+j+1]) {
increasing = false
}
if (xbar[i+j] <= xbar[i+j+1]) {
decreasing = false
}
}
if (increasing or decreasing) {
anomalies.append!("点" + string(i) + "-" + string(i+5) + "连续6点趋势")
}
}
return anomalies
}
5.2 实时异常检测
python
// 实时异常检测
share table(1:0,
`detect_time`device_id`anomaly_type`value,
[TIMESTAMP, SYMBOL, STRING, DOUBLE]) as spc_anomaly
// 订阅检测
subscribeTable(, "quality_stream", "spc_detect", -1,
def(msg) {
for (row in msg) {
// 检查是否超出规格
if (row.measurement < row.spec_min or row.measurement > row.spec_max) {
insert into spc_anomaly values (
now(), row.device_id, "out_of_spec", row.measurement
)
}
}
}, true)
六、质量告警
6.1 SPC告警规则
python
// SPC告警规则
spcAlertRules = table(
["out_of_control", "low_capability", "trend_anomaly"] as rule_name,
[1, 0, 1] as threshold,
[2, 2, 3] as alert_level
)
// 检查SPC告警
def checkSpcAlerts(deviceId) {
alerts = array(STRING, 0)
// 检查控制图异常
anomalies = detectAnomalies(deviceId)
if (anomalies.size() > 0) {
alerts.append!("控制图异常: " + concat(anomalies, ", "))
}
// 检查过程能力
capability = calculateProcessCapability(deviceId)
if (capability["Cpk"] < 1.0) {
alerts.append!("过程能力不足: Cpk=" + string(capability["Cpk"]))
}
return alerts
}
七、实战案例
7.1 完整SPC监控系统
python
// ========== SPC统计过程控制系统 ==========
// 1. 创建数据表
share streamTable(100000:0,
`product_id`device_id`timestamp`measurement`spec_min`spec_max,
[SYMBOL, SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as quality_stream
enableTablePersistence(quality_stream, true, true, 1000000)
// 2. 创建分布式表
db = database("dfs://quality_db", VALUE, 1..100)
schema = table(1:0,
`product_id`device_id`timestamp`measurement`spec_min`spec_max,
[SYMBOL, SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `quality_data, `device_id)
// 3. 订阅写入
subscribeTable(, "quality_stream", "persist", -1,
def(msg) {
loadTable("dfs://quality_db", "quality_data").append!(msg)
}, 10000, 5000)
// 4. SPC异常表
share table(1:0,
`detect_time`device_id`anomaly_type`value,
[TIMESTAMP, SYMBOL, STRING, DOUBLE]) as spc_anomaly
// 5. 实时检测
subscribeTable(, "quality_stream", "spc_detect", -1,
def(msg) {
for (row in msg) {
if (row.measurement < row.spec_min or row.measurement > row.spec_max) {
insert into spc_anomaly values (
now(), row.device_id, "out_of_spec", row.measurement
)
}
}
}, true)
// 6. 模拟数据
def generateMockQuality() {
while (true) {
data = table(
"P" + string(rand(1000, 10)) as product_id,
take(1..10, 10) as device_id,
take(now(), 10) as timestamp,
rand(95.0..105.0, 10) as measurement,
take(90.0, 10) as spec_min,
take(110.0, 10) as spec_max
)
quality_stream.append!(data)
sleep(5000)
}
}
submitJob("mock_quality", "模拟质量数据", generateMockQuality)
// 7. SPC分析接口
def getSpcAnalysis(deviceId) {
capability = calculateProcessCapability(deviceId)
chart = calculateXbarRChart(deviceId)
return dict(STRING, ANY, [
["capability", capability],
["controlChart", chart]
])
}
addFunctionView(getSpcAnalysis)
print("SPC统计过程控制系统启动完成")
八、总结
本文详细介绍了DolphinDB质量实时监控SPC:
- SPC原理:控制图、控制限
- 控制图计算:X-bar R图、P图
- 过程能力:Cp、Cpk、Pp、Ppk
- 异常检测:控制图规则、实时检测
- 质量告警:告警规则、告警推送
思考题:
- 如何选择合适的控制图类型?
- 如何提高过程能力?
- 如何实现SPC的自动化?