Carte di Controllo di Shewhart X̄-R: Guida Completa con Teoria, Python ed Esempi Pratici

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

Ogni processo produce variazioni.

Un macchinario che riempie bottiglie non versa mai esattamente la stessa quantità di liquido. Un sensore industriale oscilla continuamente. Persino un algoritmo di machine learning mostra piccole differenze nelle prestazioni quando arrivano nuovi dati.

La domanda non è eliminare completamente queste variazioni, perché sarebbe impossibile. La domanda giusta è capire quando rappresentano il comportamento normale del sistema e quando, invece, segnalano che qualcosa sta cambiando davvero.

Le carte di controllo di Shewhart nascono esattamente per questo.

Attraverso pochi indicatori statistici permettono di distinguere il rumore casuale da un’anomalia reale, trasformando una semplice sequenza di misure in uno strumento di diagnosi del processo.

In questo articolo vedremo il fondamento matematico delle carte X̄-R, il motivo per cui si analizza prima la variabilità e solo dopo la media, come interpretare correttamente le regole di Nelson e come costruire un simulatore interattivo in Python per sperimentare direttamente gli effetti di derive e anomalie.

Pubblicità

Nomenclatura delle carte di Shewhart: [math]\bar{x}[/math] e [math]R[/math]

Nella nomenclatura delle carte di Shewhart, i termini [math]\bar{x}[/math] e [math]R[/math] rappresentano le due variabili statistiche fondamentali estratte da ogni singolo sottocampione di produzione:

  1. [math]\bar{x}[/math] (Media Campionaria)
    È il baricentro del sottocampione. Si ottiene calcolando la media aritmetica delle [math]n[/math] unità misurate in quel determinato istante temporale.Cosa indica: Rappresenta la tendenza centrale del processo. Se il valore di [math]\bar{x}[/math] si sposta rispetto alla linea di riferimento (la media storica [math]\bar{\bar{x}}[/math]), significa che sta avvenendo uno spostamento sistematico della qualità del prodotto (es. un macchinario che si è starato o una temperatura che è salita).
  2. [math]R[/math] (Range / Campo di Variazione)
    È la differenza tra il valore massimo e il valore minimo riscontrati all’interno dello stesso sottocampione ([math]R = \max – \min[/math]).Cosa indica: Rappresenta la dispersione (variabilità) interna al gruppo. È una misura immediata, seppur semplificata rispetto alla deviazione standard, della “stabilità” del processo in quell’istante. Se il valore di [math]R[/math] aumenta, significa che il processo sta diventando meno prevedibile, ovvero che la variabilità intrinseca è esplosa (es. un utensile che inizia a vibrare in modo incontrollato o materiale che non è omogeneo).

Sintesi operativa: La carta [math]\bar{x}[/math] controlla dove si trova il processo (centratura), mentre la carta [math]R[/math] controlla quanto è costante il processo (variabilità).

Un primo esempio intuitivo: il riempimento delle bottiglie

Prima di affrontare le formule generali, immaginiamo un caso concreto.

Una macchina industriale deve riempire bottiglie con un volume nominale di 500 ml. Naturalmente nessun sistema reale produce valori perfettamente identici: ogni riempimento presenta piccole oscillazioni dovute a tolleranze meccaniche, pressione della pompa e variazioni del liquido.

Supponiamo di prelevare un piccolo sottocampione di 5 bottiglie consecutive:

Bottiglia Volume misurato
1 500 ml
2 501 ml
3 499 ml
4 500 ml
5 502 ml

La prima domanda è:

La macchina sta mantenendo il valore medio corretto?

Per rispondere calcoliamo la media del sottocampione:

[math]\displaystyle \bar{x} = \frac{500 + 501 + 499 + 500 + 502}{5} = 500,4 \text{ ml}[/math]

La macchina non sta quindi riempiendo esattamente a 500 ml, ma il valore medio del campione è molto vicino al valore nominale.

La seconda domanda è:

Quanto è stabile il processo?

Per questo calcoliamo il range:

[math]\displaystyle R = \max(x_i) – \min(x_i)[/math]

Nel nostro caso:

[math]\displaystyle R = 502 – 499 = 3 \text{ ml}[/math]

Il sottocampione presenta quindi una variabilità interna di 3 ml.

Questo significa che, all’interno delle cinque bottiglie osservate, la differenza tra il contenuto massimo e quello minimo è di soli 3 ml.

Ora immaginiamo di ripetere lo stesso controllo per diversi intervalli temporali.

Ogni volta otteniamo due numeri:

[math]\displaystyle \bar{x}_1, \bar{x}_2, \bar{x}_3, \ldots[/math]

che descrivono dove si trova il processo, e:

[math]\displaystyle R_1, R_2, R_3, \ldots[/math]

che descrivono quanto varia il processo.

Ad esempio:

Campione Media [math]\bar{x}[/math] (ml) Range [math]R[/math] (ml)
1 500,4 3
2 499,8 4
3 500,2 2
4 500,1 3
5 503,5 8

Osserviamo il quinto campione.

La media è salita da circa 500 ml a 503,5 ml e contemporaneamente il range è aumentato.

Questo potrebbe indicare una causa speciale:

  • una valvola di riempimento leggermente starata;
  • una variazione della pressione della pompa;
  • un problema meccanico che aumenta la dispersione.

La carta [math]\bar{x}[/math] ci segnala uno spostamento del centro del processo.

La carta [math]R[/math] ci segnala invece una perdita di stabilità della variabilità.

Questo esempio introduce il principio fondamentale delle carte di Shewhart:

Ogni processo produce variazione. La statistica non cerca di eliminare questa variazione, ma di capire quando il comportamento osservato è compatibile con il normale rumore del sistema e quando invece indica un cambiamento reale.

Solo dopo aver costruito questa intuizione diventa naturale introdurre le formule dei limiti di controllo:

[math]\displaystyle LCS_{\bar{x}} = \bar{\bar{x}} + A_2 \bar{R}[/math]

e

[math]\displaystyle LCS_R = D_4 \bar{R}[/math]

per trasformare una semplice sequenza di misure in un sistema automatico di diagnosi.

La Filosofia d’Indagine: Cause Comuni vs. Cause Speciali

Walter A. Shewhart intuì negli anni ’20 che ogni processo fisico o gestionale, per quanto perfettamente tarato, presenta un grado ineliminabile di variabilità. Per governarlo, la varianza totale va scomposta in due categorie ontologicamente diverse:

  • Cause Comuni (Aleatorie / Intrinseche): È la variabilità naturale, strutturale, che appartiene al sistema stesso (es. microscopiche vibrazioni del macchinario, tolleranze di fusione della materia prima, lievi oscillazioni termiche). Quando operano solo cause comuni, il processo si dice stabile o sotto controllo statistico: la sua distribuzione probabilistica è costante e prevedibile nel tempo.
  • Cause Speciali (Assegnabili / Esterne): Sono eventi anomali che intervengono dall’esterno perturbando il sistema (es. usura improvvisa di un utensile, un operatore non addestrato che subentra a fine turno, una partita di materia prima difettosa). Le cause speciali provocano slittamenti della media o esplosioni della variabilità, rendendo il processo fuori controllo e imprevedibile.

L’obiettivo delle carte [math]\bar{x}-R[/math] non è produrre pezzi perfetti, ma stabilire una linea base di variabilità casuale per diagnosticare tempestivamente l’insorgere di una causa speciale prima che generi scarti industriali di massa.

Il Principio della Sequenzialità: Perché la Carta [math]R[/math] Comanda sulla Carta [math]\bar{x}[/math]

Un errore comune nell’analisi dati è interpretare prima la carta delle medie ([math]\bar{x}[/math]) e poi quella dei range ([math]R[/math]). Dal punto di vista della statistica parametrica, questo approccio è scorretto.

Esiste una gerarchia di dipendenza rigorosa: la carta [math]R[/math] va sempre analizzata e validata per prima.

Il motivo risiede in un paradosso matematico del campionamento:

  1. I limiti di controllo della carta delle medie non si calcolano sulla deviazione standard empirica globale di tutti i dati storici, ma utilizzando la stima della varianza interna ai singoli sottocampioni, derivata proprio dal range medio ([math]\bar{R}[/math]).
  2. Se la carta [math]R[/math] è fuori controllo (la dispersione del processo è instabile), il valore [math]\bar{R}[/math] perde valore statistico: non rappresenta più una stima fedele e costante della deviazione standard della popolazione ([math]\sigma[/math]).
  3. Di conseguenza, se la varianza è instabile, i limiti di controllo calcolati per la carta [math]\bar{x}[/math] risulterebbero artificialmente larghi o stretti (e quindi privi di validità inferenziale).
Forse potrebbe interessarti anche:  Test t di Welch: La Guida Pratica per Scegliere il Test Statistico Giusto (con Esempi in Python)

In sintesi: prima si stabilizza la dispersione del processo (Carta [math]R[/math]), e solo quando la varianza è costante ha senso valutare se il valore medio ([math]\bar{x}[/math]) è centrato.

Fondamento Matematico e Costruzione dei Limiti

Si prelevano [math]k[/math] sottocampioni (generalmente [math]k \ge 20[/math] o [math]30[/math] per la configurazione iniziale di Fase 1), ciascuno costituito da un numero costante di unità [math]n[/math] (tipicamente tra [math]n=3[/math] e [math]n=8[/math]).

Per ogni campionamento [math]i[/math]-esimo si calcolano la media campionaria e il campo di variazione:

[math]\displaystyle \bar{x}_i = \frac{1}{n} \sum_{j=1}^{n} x_{ij} \quad \text{e} \quad R_i = \max(x_{ij}) – \min(x_{ij})[/math]

Le medie generali di riferimento del processo (le Linee Centrali, Center Lines o [math]CL[/math]) sono:

[math]\displaystyle \bar{\bar{x}} = \frac{1}{k} \sum_{i=1}^{k} \bar{x}_i \quad \text{e} \quad \bar{R} = \frac{1}{k} \sum_{i=1}^{k} R_i[/math]

Derivazione Parametrica dei Limiti a [math]3\sigma[/math]

Per il Teorema del Limite Centrale, la distribuzione delle medie campionarie [math]\bar{x}[/math] tende a una Normalità statistica con deviazione standard dell’errore standard [math]\sigma_{\bar{x}} = \frac{\sigma}{\sqrt{n}}[/math]. La teoria del controllo di Shewhart fissa i limiti a [math]\pm 3\sigma_{\bar{x}}[/math], coprendo il [math]99,73\%[/math] della variazione casuale per una distribuzione normale (rischio di falso allarme di circa [math]0,27\%[/math], o errore di Tipo I).

Poiché la vera deviazione standard della popolazione ([math]\sigma[/math]) è incognita in ambiente produttivo, la si stima a partire dal range medio usando il parametro di correzione per la varianza campionaria [math]d_2[/math]:

[math]\displaystyle \hat{\sigma} = \frac{\bar{R}}{d_2}[/math]

Sostituendo questa stima nell’equazione teorica dei limiti della media si ottiene la formulazione operativa:

[math]\displaystyle LCS_{\bar{x}} = \bar{\bar{x}} + 3 \frac{\hat{\sigma}}{\sqrt{n}} = \bar{\bar{x}} + \frac{3}{d_2 \sqrt{n}} \bar{R} = \bar{\bar{x}} + A_2 \bar{R}[/math]

[math]\displaystyle LCI_{\bar{x}} = \bar{\bar{x}} – A_2 \bar{R}[/math]

In modo analogo, per la distribuzione campionaria dei range (che è asimmetrica per piccoli campioni), la deviazione standard del range è [math]\sigma_R = d_3 \sigma = d_3 \frac{\bar{R}}{d_2}[/math]. I limiti inferiori e superiori del range si compattano nei coefficienti [math]D_3[/math] e [math]D_4[/math]:

[math]\displaystyle LCS_R = \bar{R} + 3\sigma_R = \left(1 + 3 \frac{d_3}{d_2}\right) \bar{R} = D_4 \bar{R}[/math]

[math]\displaystyle LCI_R = \bar{R} – 3\sigma_R = \left(1 – 3 \frac{d_3}{d_2}\right) \bar{R} = D_3 \bar{R}[/math]

Abaco delle Costanti Tabulari (Normale Standard)

Per facilitare il calcolo, si utilizzano i coefficienti standardizzati in funzione dell’ampiezza campionaria [math]n[/math]:

Dimensione n Coefficiente A2 Coefficiente D3 Coefficiente D4 Divisore d2
2 1,880 0 3,267 1,128
3 1,023 0 2,574 1,693
4 0,729 0 2,282 2,059
5 0,577 0 2,114 2,326
6 0,483 0 2,004 2,534
8 0,373 0,136 1,864 2,847
10 0,308 0,223 1,777 3,078

(Nota operativa: per [math]n \le 6[/math], la distribuzione del range impedisce matematicamente limiti inferiori negativi, motivo per cui [math]D_3 = 0[/math] e il [math]LCI_R[/math] coincide con zero).

Diagnostica e Segnali di Allarme: Le Regole di Nelson e Western Electric

Un processo non è fuori controllo solo quando un punto supera fisicamente le linee [math]LCS[/math] o [math]LCI[/math]. L’inferenza statistica permette di identificare squilibri probabilistici analizzando i pattern sequenziali dei punti all’interno delle bande di variabilità [math]\pm 1\sigma[/math], [math]\pm 2\sigma[/math] e [math]\pm 3\sigma[/math].

Le quattro regole principali ispirate ai criteri Western Electric e successivamente estese dalle Nelson Rules (le Nelson Rules sono 8), sono:

  1. Violazione dei Limiti (Oltre [math]3\sigma[/math]): 1 singolo punto cade al di fuori dei limiti di controllo superiori o inferiori. Indica uno shock istantaneo e violento sul processo.
  2. Deriva del Processo (Run Rule): 8 (o 9) punti consecutivi cadono rigorosamente dallo stesso lato della Linea Centrale ([math]\bar{\bar{x}}[/math] o [math]\bar{R}[/math]). La probabilità casuale che ciò accada è [math]\left(\frac{1}{2}\right)^8 \approx 0,0039[/math], paragonabile al rischio di un punto oltre [math]3\sigma[/math]. Segnala uno shift stabile della media (es. cambio di turno o di lotto di materia prima).
  3. Trend Monotono (Trend Rule): 6 punti consecutivi costantemente in crescita o costantemente in decrescita. Evidenzia un degrado progressivo e lineare nel tempo (es. logoramento di una fresa, riscaldamento graduale di un motore, affaticamento dell’operatore).
  4. Alternanza Sistematica (Ciclicità): 14 punti che alternano regolarmente salite e discese a zig-zag. Spesso sintomo di sovracontrollo (l’operatore aggiusta il macchinario ad ogni singolo pezzo misurato) o della miscelazione di due flussi di produzione paralleli e distinti (es. due teste di riempimento sullo stesso nastro).

Controllo Statistico vs. Process Capability ([math]C_p, C_{pk}[/math])

Una delle concettualizzazioni più critiche nell’analisi aziendale è la netta distinzione tra Stabilità e Idoneità/Capacità.

  • I Limiti di Controllo (LCS/LCI): Parlano la lingua della macchina. Calcolati sulla dispersione intrinseca del processo ([math]\pm 3\sigma_{\bar{x}}[/math]), descrivono ciò che il processo sta facendo in condizioni normali.
  • I Limiti di Specifica (USL/LSL): Parlano la lingua del cliente o dell’ingegneria di progetto. Rappresentano i requisiti contrattuali di accettabilità del prodotto finito.

Un processo può essere perfettamente in controllo statistico (nessun punto anomalo, variabilità costante e casuale) ma produrre sistematicamente scarti, perché la sua campana gaussiana è semplicemente più larga della finestra di tolleranza concessa dal cliente:

[math]\displaystyle \text{Varianza Naturale del Processo } (6\hat{\sigma}) > \text{Tolleranza del Cliente } (USL – LSL)[/math]

Gli indici di capability quantificano questo rapporto:

[math]\displaystyle C_p = \frac{USL – LSL}{6 \hat{\sigma}} \quad \text{e} \quad C_{pk} = \min \left( \frac{USL – \bar{\bar{x}}}{3\hat{\sigma}} , \frac{\bar{\bar{x}} – LSL}{3\hat{\sigma}} \right)[/math]

  • Se [math]C_p < 1[/math]: La dispersione naturale è incompatibile con le specifiche. L’azienda, pur in controllo, genererà difetti sistematici. L’unica soluzione è reingegnerizzare il macchinario per abbattere [math]\hat{\sigma}[/math].
  • Se [math]C_p \ge 1,33[/math]: Il processo è adeguatamente capace e assorbe lievi fluttuazioni senza generare non conformità (standard industriale minimo per la qualità e il cost-saving).

Key insight:

Il vero valore gestionale della carta [math]\bar{x}-R[/math] non risiede nel documentare un errore già avvenuto (adempimento burocratico della qualità), ma nella funzione predittiva: i pattern sequenziali all’interno dei limiti agiscono come un sistema radar che avvisa l’analista di una deriva di processo prima che il prodotto varchi i limiti contrattuali di scarto.


Perché un Data Scientist dovrebbe conoscere le carte di controllo di Shewhart

Per molti anni le carte di controllo sono state considerate strumenti esclusivi dell’ingegneria della qualità e delle linee di produzione. Oggi questa distinzione è sempre meno netta. L’evoluzione dell’Industria 4.0, la diffusione dei sensori IoT e l’analisi dei dati in tempo reale hanno trasformato il Controllo Statistico di Processo (SPC) in una competenza sempre più rilevante anche per Data Scientist, Machine Learning Engineer e Data Engineer.

Alla base delle carte di Shewhart c’è un problema universale dell’analisi dei dati: distinguere una normale oscillazione casuale da un cambiamento reale del sistema. È la stessa domanda che ci poniamo quando monitoriamo un modello di machine learning, una pipeline ETL o una rete di sensori industriali.

Oggi le carte di controllo vengono integrate in numerosi contesti:

  • Industria 4.0, per monitorare in tempo reale linee produttive completamente automatizzate.
  • Sensoristica IoT, dove migliaia di sensori trasmettono continuamente misure di temperatura, pressione, vibrazioni o consumi energetici.
  • Streaming Analytics, per individuare anomalie su flussi di dati continui senza attendere analisi offline.
  • Manutenzione predittiva, identificando piccoli cambiamenti nel comportamento delle macchine prima che si trasformino in guasti.
  • Controllo qualità automatico, combinando algoritmi di visione artificiale, sensori e SPC per rilevare difetti durante la produzione.
  • Data Lake e Data Pipeline, dove le carte di controllo aiutano a verificare la stabilità dei processi di acquisizione dei dati e a individuare rapidamente errori di ingestione o trasformazione.
  • Monitoraggio dei modelli di Machine Learning, controllando nel tempo metriche come accuratezza, errore, latenza o tasso di falsi positivi per individuare fenomeni di model drift e data drift.
Forse potrebbe interessarti anche:  Simulazione Monte Carlo e Rischio di Credito: Calcolo di EL, UL e VaR con Python

Dal punto di vista concettuale, le carte di Shewhart rappresentano uno dei primi algoritmi di anomaly detection sviluppati nella storia della statistica applicata. Pur essendo nate quasi un secolo fa, condividono con molte tecniche moderne lo stesso obiettivo: rilevare tempestivamente deviazioni significative rispetto al comportamento atteso del sistema.

Naturalmente oggi il Data Scientist dispone anche di strumenti più sofisticati, come algoritmi di rilevamento delle anomalie basati su machine learning, modelli probabilistici o reti neurali. Tuttavia, le carte di controllo mantengono un vantaggio fondamentale: sono semplici da interpretare, richiedono poche ipotesi, hanno un costo computazionale trascurabile e permettono di spiegare in modo trasparente perché un processo è stato classificato come anomalo. Per questo motivo continuano a essere utilizzate come primo livello di sorveglianza in molti sistemi di monitoraggio industriale e nelle moderne piattaforme MLOps.

Dalla qualità industriale ai sistemi intelligenti

Le carte di controllo di Shewhart non sono soltanto uno strumento storico dello Statistical Process Control. Rappresentano uno dei primi esempi di monitoraggio continuo basato sui dati e costituiscono ancora oggi un riferimento per comprendere come distinguere il rumore statistico da un cambiamento strutturale. Questo principio è alla base di numerose applicazioni contemporanee, dal monitoraggio delle pipeline dati fino alla sorveglianza dei modelli di intelligenza artificiale.

Simulatore Interattivo per Carte di Controllo [math]\bar{x}-R[/math]

Pubblicità

Dalla teoria alla sperimentazione

Le formule mostrano come costruire una carta di controllo, ma è solo osservandone il comportamento su dati simulati che se ne comprendono davvero le potenzialità. Vedere come i limiti di controllo reagiscono a uno spostamento della media, a un aumento della variabilità o a una sequenza di piccoli segnali anomali permette di sviluppare un’intuizione statistica che va oltre il semplice calcolo dei coefficienti.

Per questo motivo realizzeremo un simulatore interattivo in Python, eseguibile su Google Colab. Attraverso alcuni controlli sarà possibile modificare in tempo reale la dimensione dei sottocampioni, la variabilità del processo e introdurre deliberatamente cause speciali, osservando come cambiano le carte [math]\bar{x}[/math] e [math]R[/math], gli allarmi statistici e gli indici di capability.

L’obiettivo non è soltanto visualizzare i grafici, ma sperimentare direttamente i principi discussi nelle sezioni precedenti. Ogni parametro modificato permette di verificare una proprietà teorica delle carte di Shewhart e di capire perché queste continuino a essere uno degli strumenti più efficaci per il monitoraggio dei processi, dalle linee di produzione tradizionali fino ai moderni sistemi di analisi dati in tempo reale.

Lo script implementa un ambiente di test con interfaccia a slider (ipywidgets) che consente di manipolare in tempo reale la dimensione campionaria [math]n[/math], la variabilità naturale del processo [math]\sigma[/math], e di indurre shock artificiali (slittamenti della media o esplosioni della varianza) in un punto esatto della produzione per osservare la reazione dei limiti e degli allarmi statistici.

Come eseguire il cruscotto in Google Colab

  1. Apri un nuovo taccuino su Google Colab.
  2. Copia l’intero blocco di codice sottostante e incollalo in una singola cella.
  3. Esegui la cella (Shift + Enter). L’interfaccia interattiva comparirà immediatamente sotto il blocco di codice.
import numpy as np
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, HTML

# Configurazione stile grafico per un layout pulito
plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.available else 'default')
plt.rcParams['font.family'] = 'sans-serif'

# ==============================================================================
# 1. ABACO DELLE COSTANTI DI SHEWHART (Distribuzione Normale Standard)
# ==============================================================================
SHEWHART_CONSTANTS = {
    2:  {'A2': 1.880, 'D3': 0.000, 'D4': 3.267, 'd2': 1.128},
    3:  {'A2': 1.023, 'D3': 0.000, 'D4': 2.574, 'd2': 1.693},
    4:  {'A2': 0.729, 'D3': 0.000, 'D4': 2.282, 'd2': 2.059},
    5:  {'A2': 0.577, 'D3': 0.000, 'D4': 2.114, 'd2': 2.326},
    6:  {'A2': 0.483, 'D3': 0.000, 'D4': 2.004, 'd2': 2.534},
    7:  {'A2': 0.419, 'D3': 0.076, 'D4': 1.924, 'd2': 2.704},
    8:  {'A2': 0.373, 'D3': 0.136, 'D4': 1.864, 'd2': 2.847},
    9:  {'A2': 0.337, 'D3': 0.184, 'D4': 1.816, 'd2': 2.970},
    10: {'A2': 0.308, 'D3': 0.223, 'D4': 1.777, 'd2': 3.078}
}

# ==============================================================================
# 2. MOTORE DI SIMULAZIONE E DIAGNOSTICA SPC
# ==============================================================================
def run_spc_simulation(n, k_samples, mu_target, sigma_base, 
                       shift_mean, shift_start, 
                       sigma_mult, var_start, 
                       freeze_baseline, seed):
    
    np.random.seed(seed)
    
    # Inizializzazione matrici dati (k sottocampioni di dimensione n)
    data = np.zeros((k_samples, n))
    
    # Generazione dati con iniezione di derive (Shift Media ed Esplosione Varianza)
    for i in range(k_samples):
        current_mu = mu_target + shift_mean if (i + 1) >= shift_start else mu_target
        current_sigma = sigma_base * sigma_mult if (i + 1) >= var_start else sigma_base
        data[i, :] = np.random.normal(loc=current_mu, scale=current_sigma, size=n)
        
    # Calcolo statistiche di sottocampione
    x_bars = np.mean(data, axis=1)
    ranges = np.ptp(data, axis=1) # ptp = peak-to-peak (max - min)
    
    # Prelievo costanti tabulari per la dimensione n
    const = SHEWHART_CONSTANTS[n]
    A2, D3, D4, d2 = const['A2'], const['D3'], const['D4'], const['d2']
    
    # Calcolo Linee Centrali (CL) e Limiti di Controllo (LCS / LCI)
    idx_end = min(15, k_samples) if freeze_baseline else k_samples
    
    x_cl = np.mean(x_bars[:idx_end])
    r_cl = np.mean(ranges[:idx_end])
    
    # Limiti Carta X-bar
    ucl_x = x_cl + A2 * r_cl
    lcl_x = x_cl - A2 * r_cl
    
    # Limiti Carta R
    ucl_r = D4 * r_cl
    lcl_r = D3 * r_cl
    
    # Stima della deviazione standard del processo (sigma cappello)
    sigma_hat = r_cl / d2
    
    # Calcolo Capability
    usl = mu_target + (3.5 * sigma_base)
    lsl = mu_target - (3.5 * sigma_base)
    cp = (usl - lsl) / (6 * sigma_hat) if sigma_hat > 0 else 0
    cpk = min((usl - x_cl) / (3 * sigma_hat), (x_cl - lsl) / (3 * sigma_hat)) if sigma_hat > 0 else 0
    
    # Diagnostica Allarmi
    out_x = (x_bars > ucl_x) | (x_bars < lcl_x)
    out_r = (ranges > ucl_r) | (ranges < lcl_r)
    
    run_rule_x = np.zeros(k_samples, dtype=bool)
    for i in range(7, k_samples):
        if np.all(x_bars[i-7:i+1] > x_cl) or np.all(x_bars[i-7:i+1] < x_cl):
            run_rule_x[i] = True
            
    return {
        'x_bars': x_bars, 'ranges': ranges,
        'x_cl': x_cl, 'ucl_x': ucl_x, 'lcl_x': lcl_x,
        'r_cl': r_cl, 'ucl_r': ucl_r, 'lcl_r': lcl_r,
        'sigma_hat': sigma_hat, 'cp': cp, 'cpk': cpk,
        'out_x': out_x, 'out_r': out_r, 'run_rule_x': run_rule_x,
        'usl': usl, 'lsl': lsl
    }

# ==============================================================================
# 3. MOTORE GRAFICO E RENDERING INTERFACCIA
# ==============================================================================
def render_dashboard(n, k_samples, sigma_base, shift_mean, shift_start, 
                     sigma_mult, var_start, freeze_baseline, seed):
    
    mu_target = 1.50 # Valore nominale di riferimento
    res = run_spc_simulation(n, k_samples, mu_target, sigma_base, 
                             shift_mean, shift_start, 
                             sigma_mult, var_start, 
                             freeze_baseline, seed)
    
    # Creazione Dashboard a 2 pannelli
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(13, 8), sharex=True)
    samples = np.arange(1, k_samples + 1)
    
    # --- PANNELLO 1: CARTA X-BAR (con escape LaTeX corretti tramite doppio backslash) ---
    ax1.plot(samples, res['x_bars'], marker='o', color='#1f77b4', linestyle='-', linewidth=1.5, label='Media Campionaria ($\\bar{x}$)')
    ax1.axhline(res['ucl_x'], color='#d62728', linestyle='--', linewidth=1.5, label=f"LCS: {res['ucl_x']:.4f}")
    ax1.axhline(res['x_cl'], color='#2ca02c', linestyle='-', linewidth=1.5, label=f"CL ($\\bar{{\\bar{{x}}}}$): {res['x_cl']:.4f}")
    ax1.axhline(res['lcl_x'], color='#d62728', linestyle='--', linewidth=1.5, label=f"LCI: {res['lcl_x']:.4f}")
    
    # Evidenziazione Allarmi X-Bar
    if np.any(res['out_x']):
        ax1.scatter(samples[res['out_x']], res['x_bars'][res['out_x']], color='#d62728', s=100, zorder=5, label='Allarme: Violazione >3σ')
    if np.any(res['run_rule_x']):
        ax1.scatter(samples[res['run_rule_x']], res['x_bars'][res['run_rule_x']], color='#ff7f0e', s=100, marker='X', zorder=5, label='Allarme: Run Rule (8 pt)')
        
    ax1.set_title(f"Carta di Controllo delle Medie ($\\bar{{x}}$) — Dimensione Sottocampione $n={n}$", fontsize=13, fontweight='bold')
    ax1.set_ylabel("Media del Sottocampione", fontsize=11)
    ax1.legend(loc='upper right', frameon=True, facecolor='white', framealpha=0.9, fontsize=9)
    ax1.set_xlim(0.5, k_samples + 0.5)
    
    # --- PANNELLO 2: CARTA R ---
    ax2.plot(samples, res['ranges'], marker='s', color='#9467bd', linestyle='-', linewidth=1.5, label='Range Campione ($R$)')
    ax2.axhline(res['ucl_r'], color='#d62728', linestyle='--', linewidth=1.5, label=f"LCS: {res['ucl_r']:.4f}")
    ax2.axhline(res['r_cl'], color='#2ca02c', linestyle='-', linewidth=1.5, label=f"CL ($\\bar{{R}}$): {res['r_cl']:.4f}")
    ax2.axhline(res['lcl_r'], color='#d62728', linestyle='--', linewidth=1.5, label=f"LCI: {res['lcl_r']:.4f}")
    
    # Evidenziazione Allarmi R
    if np.any(res['out_r']):
        ax2.scatter(samples[res['out_r']], res['ranges'][res['out_r']], color='#d62728', s=100, zorder=5, label='Allarme: Varianza Anomala (>3σ)')
        
    ax2.set_title("Carta di Controllo dei Range ($R$)", fontsize=13, fontweight='bold')
    ax2.set_xlabel("Numero del Sottocampione (Sequenza Temporale)", fontsize=11)
    ax2.set_ylabel("Campo di Variazione ($R$)", fontsize=11)
    ax2.legend(loc='upper right', frameon=True, facecolor='white', framealpha=0.9, fontsize=9)
    ax2.set_xticks(samples)
    
    plt.tight_layout()
    plt.show()
    
    # --- PANNELLO METRICHE SINTETICHE (HTML) ---
    stato_cpk = "<span style='color:green;font-weight:bold;'>IDONEO (Cpk ≥ 1.33)</span>" if res['cpk'] >= 1.33 else "<span style='color:red;font-weight:bold;'>NON IDONEO (Cpk < 1.33)</span>"
    allarmi_tot = np.sum(res['out_x']) + np.sum(res['out_r']) + np.sum(res['run_rule_x'])
    stato_controllo = "<span style='color:green;font-weight:bold;'>STABILE / IN CONTROLLO</span>" if allarmi_tot == 0 else f"<span style='color:red;font-weight:bold;'>FUORI CONTROLLO ({allarmi_tot} segnali rilevati)</span>"
    
    html_out = f"""
    <div style="background-color: #f8f9fa; border-left: 5px solid #1f77b4; padding: 15px; margin-top: 10px; border-radius: 4px; font-family: sans-serif;">
        <h4 style="margin-top: 0; color: #333;">Dati Diagnostici e Capability di Processo</h4>
        <div style="display: flex; justify-content: space-between; flex-wrap: wrap;">
            <div style="flex: 1; min-width: 200px;">
                <b>Stato del Controllo:</b> {stato_controllo}<br>
                <b>Stima Varianza ($\hat{{\sigma}} = \\bar{{R}}/d_2$):</b> {res['sigma_hat']:.5f} (reale: {sigma_base:.5f})<br>
                <b>Modalità Calcolo Limiti:</b> {'Fase 1 congelata (Campioni 1-15)' if freeze_baseline else 'Dinamica su tutti i campioni'}
            </div>
            <div style="flex: 1; min-width: 200px;">
                <b>Indice $C_p$ (Potenziale):</b> {res['cp']:.2f}<br>
                <b>Indice $C_{{pk}}$ (Centratura):</b> {res['cpk']:.2f}<br>
                <b>Valutazione Capability:</b> {stato_cpk}
            </div>
        </div>
    </div>
    """
    display(HTML(html_out))

# ==============================================================================
# 4. CREAZIONE DELL'INTERFACCIA A CONTROLLI WIDGET
# ==============================================================================
style = {'description_width': '220px'}
layout = widgets.Layout(width='450px')

w_n = widgets.Dropdown(options=[2, 3, 4, 5, 6, 7, 8, 9, 10], value=4, description='Dimensione Sottocampione (n):', style=style, layout=layout)
w_k = widgets.IntSlider(value=30, min=20, max=50, step=5, description='Numero Campioni (k):', style=style, layout=layout)
w_sigma = widgets.FloatSlider(value=0.03, min=0.01, max=0.08, step=0.005, description='Varianza Naturale (σ base):', style=style, layout=layout)

w_shift_mean = widgets.FloatSlider(value=0.00, min=-0.08, max=0.08, step=0.01, description='Slittamento Media (Δμ):', style=style, layout=layout)
w_shift_start = widgets.IntSlider(value=16, min=1, max=50, step=1, description='Inizio Slittamento Media (Campione):', style=style, layout=layout)

w_sigma_mult = widgets.FloatSlider(value=1.0, min=1.0, max=3.0, step=0.2, description='Moltiplicatore Varianza (x σ):', style=style, layout=layout)
w_var_start = widgets.IntSlider(value=20, min=1, max=50, step=1, description='Inizio Esplosione Varianza:', style=style, layout=layout)

w_freeze = widgets.Checkbox(value=True, description='Congela Limiti sulla Fase 1 (primi 15 campioni)', style=style, layout=widgets.Layout(width='400px'))
w_seed = widgets.IntSlider(value=42, min=1, max=100, step=1, description='Seed Aleatorio:', style=style, layout=layout)

# Raggruppamento in pannelli affiancati per una UI compatta
ui_left = widgets.VBox([widgets.HTML("<b>1. Parametri Strutturali e Varianza</b>"), w_n, w_k, w_sigma, w_seed, w_freeze])
ui_right = widgets.VBox([widgets.HTML("<b>2. Iniezione Anomalie (Cause Speciali)</b>"), w_shift_mean, w_shift_start, w_sigma_mult, w_var_start])
ui = widgets.HBox([ui_left, ui_right], layout=widgets.Layout(margin='0 0 20px 0', justify_content='space-around'))

# Collegamento tra UI e funzione di rendering
out = widgets.interactive_output(render_dashboard, {
    'n': w_n, 'k_samples': w_k, 'sigma_base': w_sigma,
    'shift_mean': w_shift_mean, 'shift_start': w_shift_start,
    'sigma_mult': w_sigma_mult, 'var_start': w_var_start,
    'freeze_baseline': w_freeze, 'seed': w_seed
})

display(ui, out)

Esperimenti pratici da condurre nel cruscotto

Una volta avviato lo script in Colab, puoi utilizzare i cursori per verificare empiricamente i principi matematici e le gerarchie di dipendenza delle carte di Shewhart:

Forse potrebbe interessarti anche:  Distribuzione Esponenziale: Cos'è e Come Prevedere i Tempi di Attesa (Guida con Esempi)

A. Il paradosso del campionamento ([math]n[/math]) e la sensibilità

Azione: Lascia tutti i parametri invariati, imposta uno Slittamento Media ([math]\Delta\mu[/math]) = 0.03 dal campione 16. Muovi il cursore della Dimensione Sottocampione ([math]n[/math]) passando da [math]n=2[/math] a [math]n=10[/math].

Osservazione: Noterai che con [math]n=2[/math] lo slittamento di [math]0.03[/math] fa fatica a uscire dai limiti di controllo (i limiti sono ampi perché l’errore standard [math]\sigma_{\bar{x}} = \frac{\sigma}{\sqrt{2}}[/math] è grande). Portando [math]n=8[/math] o [math]10[/math], le linee [math]LCS[/math] e [math]LCI[/math] della carta superiore si stringono drasticamente verso la linea centrale: quasi tutti i punti dal campione 16 in poi finiscono immediatamente in allarme rosso (violazione [math]>3\sigma[/math]), dimostrando l’aumento del potere statistico della carta al crescere di [math]n[/math].

B. Perché la carta [math]R[/math] va analizzata prima della carta [math]\bar{x}[/math]

Azione: Togli lo slittamento della media ([math]\Delta\mu = 0.00[/math]). Imposta un Moltiplicatore Varianza = 2.4x a partire dal campione 18. Deseleziona la spunta “Congela Limiti sulla Fase 1”.

Osservazione: La carta [math]R[/math] mostra un’esplosione immediata dei range oltre il limite superiore. Ma osserva cosa accade alla carta [math]\bar{x}[/math]: i suoi limiti di controllo si allargano artificialmente su tutta la linea temporale, perché calcolati su un [math]\bar{R}[/math] gonfiato dall’anomalia nella varianza. Questo dimostra visivamente perché un’instabilità della dispersione rende del tutto inaffidabili i limiti di controllo della media.

C. La potenza diagnostica delle “Run Rules” (Nelson / Western Electric)

Azione: Imposta uno slittamento lieve della media: [math]\Delta\mu = 0.02[/math] dal campione 10 con la spunta “Congela Limiti” attiva.

Osservazione: Nessun punto supera fisicamente le linee tratteggiate rosse dei [math]3\sigma[/math] (nessuna violazione violenta). Tuttavia, attorno al campione 17 o 18 appariranno dei marcatori arancioni a forma di “X”: l’algoritmo ha intercettato 8 campioni consecutivi caduti rigorosamente al di sopra della linea centrale [math]\bar{\bar{x}}[/math], segnalando all’analista una deriva strutturale prima che si verifichi un singolo scarto industriale.

Perché questi esperimenti sono interessanti

Esperimento A – L’effetto della dimensione campionaria

Questo esercizio mostra uno dei principi fondamentali della statistica inferenziale: aumentando il numero di osservazioni in ciascun sottocampione diminuisce l’errore standard della media. Di conseguenza, le carte [math]\bar{x}[/math] diventano più sensibili agli spostamenti della media del processo. È un esempio concreto di come la progettazione del piano di campionamento influenzi direttamente la capacità di individuare anomalie.

Esperimento B – La gerarchia tra carta [math]R[/math] e carta [math]\bar{x}[/math]

È probabilmente l’esercizio più importante dell’intero articolo. Dimostra che i limiti della carta delle medie dipendono dalla stima della variabilità interna del processo. Se la dispersione cambia, anche i limiti della carta [math]\bar{x}[/math] perdono significato statistico. Questo principio viene spesso trascurato nelle applicazioni pratiche, ma rappresenta uno dei fondamenti dello Statistical Process Control.

Esperimento C – Quando l’anomalia è invisibile

Molti guasti reali non producono immediatamente punti oltre i limiti di controllo. Al contrario, si manifestano come piccoli spostamenti persistenti della media. Le regole di Western Electric e Nelson permettono di individuare questi segnali deboli molto prima che il processo inizi a produrre pezzi fuori specifica. L’esercizio mostra come l’analisi dei pattern temporali possa essere più informativa della semplice verifica dei limiti a [math]\pm 3\sigma[/math].

 

Pubblicità