多產線混批的抽驗命中機率
程式碼:examples/r/sampling-probability/
問題
幾條產線各有不同的不良率,產出混在一起出貨。客戶連續驗了 4 批,每批抽 1 包,一次都沒抽到不良。
這代表什麼?是我們運氣好,還是不良率其實沒那麼高?
模型
分兩層:
① 單抽命中機率 p ← 各產線不良率,以「產量佔比」加權
② n 批的中批數 ← Binomial(n, p_batch)
single_draw_p <- function(qty, rate) {
total <- sum(qty)
sum((qty / total) * rate) # 加權平均
}
hit_distribution <- function(qty, rate, n_batch, m_per_batch = 1) {
p <- single_draw_p(qty, rate)
p_batch <- 1 - (1 - p)^m_per_batch # 每批抽 m 包,任一包不良就算中
k <- 0:n_batch
prob <- dbinom(k, size = n_batch, prob = p_batch)
list(p_single = p, p_batch = p_batch,
table = data.frame(k = k, prob = prob),
p_none = prob[1], p_at_least1 = 1 - prob[1],
expected = n_batch * p_batch)
}
算一次
B 產線 12,497 件、不良率 19.08%;C 產線 52,503 件、全良品。總共 65,000 件。
單抽命中機率 p = 0.036684 (3.6684%)
連續 4 批、每批抽 1 包:
k prob pct
0 0.861144 86.1144
1 0.131171 13.1171
2 0.007493 0.7493
3 0.000190 0.0190
4 0.000002 0.0002
P(一次都沒中) = 86.11%
P(至少中 1 批) = 13.89%
四批全過完全不能證明沒問題。 就算真的有 19% 不良的一整條產線混在裡面, 四批每批抽一包也有 86% 的機率一次都抓不到。 「沒抽到」不是「沒有」——這是抽樣檢驗最重要、也最常被誤解的一件事。
反過來用:要驗幾批才夠
這才是這個模型真正有用的地方。
batches_needed <- function(qty, rate, conf = 0.95, m_per_batch = 1) {
p_batch <- 1 - (1 - single_draw_p(qty, rate))^m_per_batch
ceiling(log(1 - conf) / log(1 - p_batch))
}
=== 每批多抽幾包的效果(連續 4 批)===
每批抽 1 包:P(至少中 1 批) = 13.89%
每批抽 2 包:P(至少中 1 批) = 25.84%
每批抽 3 包:P(至少中 1 批) = 36.14%
每批抽 5 包:P(至少中 1 批) = 52.64%
每批抽 10 包:P(至少中 1 批) = 77.57%
=== 要幾批才有 95% 把握抓到 ===
每批抽 1 包 -> 需要 81 批
每批抽 2 包 -> 需要 41 批
每批抽 5 包 -> 需要 17 批
多抽幾包比多驗幾批有效率得多。 這個數字可以直接拿去跟客戶或主管討論抽驗計畫。
前提:這個加權平均什麼時候不成立
p = Σ (qty_i / total) × rate_i 假設抽出來的那一包是從混合後的整體隨機抽的。
不成立的情況:
| 情況 | 為什麼不能用加權平均 |
|---|---|
| 每批只來自某一條產線 | 該批的 p 就是那條線自己的不良率,不是平均 |
| 依產線分棧板、抽樣時只抽某幾板 | 抽到的機率不等於產量佔比 |
| 不良集中在某個時段 | 同一條線內部也不是均勻的 |
批次沒有真正混合的話,加權平均會嚴重低估風險。 如果客戶剛好整批都拿到 B 產線的貨,他看到的是 19.08%,不是 3.67%。 用這個模型之前先確認:出貨批是不是真的混過?
二項還是超幾何
dbinom() 假設抽出放回(或母體無限大)。嚴格說抽驗是不放回,該用超幾何分布 dhyper()。
但當批量 ≫ 抽樣數時兩者幾乎相同。經驗法則:抽樣數 < 批量的 10% 就用二項分布,誤差可以忽略。
65,000 件抽 4 包,比例是 0.006%——差異在小數點後很多位,不用理會。
反過來,批量 50 件抽 5 件(10%)就該用超幾何:
# 批量 N=50,其中 D=10 件不良,抽 n=5 件,抓到 k 件的機率
dhyper(k, m = 10, n = 40, k = 5)
輸入正規化的歧義
原始版本有這個貼心設計:
norm_rate <- function(x) {
if (x > 1) x <- x / 100 # 允許填 19.08 或 0.1908
x
}
方便,但有個無法消除的歧義:使用者輸入 0.5,是 0.5% 還是 50%?
依這個規則會被當成 50%——差了一百倍,而且不會有任何警告。
處理方式二選一:
# 方式一:接受寬鬆輸入,但介面上明確標示規則,並加上範圍檢查
normalize_rate <- function(x) {
x <- as.numeric(x)
if (is.na(x) || x < 0) stop("不良率不能為負數")
if (x > 100) stop(sprintf("不良率 %g 超出範圍", x))
if (x > 1) x / 100 else x # 標籤要寫清楚:「>1 視為百分比」
}
# 方式二:強制單位,不猜
# numericInput("B_def", "B 產線不良率 (%)", value = 19.08, min = 0, max = 100)
# rate <- input$B_def / 100
方式二比較好。 少一個猜測就少一種錯法,而且 0.5% 這種真實會出現的低不良率才填得進去。
你該檢查的
- 出貨批是不是真的混合過?沒混的話加權平均不成立
- 抽樣數有沒有超過批量的 10%?超過要改用超幾何
- 不良率輸入的單位是否明確?
0.5會被解讀成什麼? - 有沒有把「四批全過」當成「沒問題」的證據?