第1章:品質管理の基礎とTQM

品質の基本概念からプロセス能力評価まで

📖 読了時間: 25-30分 📊 難易度: 入門 💻 コード例: 8個

学習目標

この章を読むことで、以下を習得できます:


1.1 品質管理の基本概念

品質とは何か

品質(Quality)とは、「製品またはサービスが、顧客の要求事項を満たす度合い」を指します。ISO 9000では「固有の特性の集まりが要求事項を満たす程度」と定義されています。

品質管理の発展は、以下の3つの時代に区分されます:

時代 アプローチ 特徴 代表的手法
検査の時代 事後検査 不良品を除去 全数検査、抜き取り検査
統計的品質管理 プロセス管理 不良を予防 管理図、サンプリング
TQM 全社的改善 顧客満足最大化 Six Sigma、ISO 9001

QC、QA、QMSの違い

graph TB A[QMS 品質マネジメントシステム] --> B[QA 品質保証] A --> C[QC 品質管理] B --> D[プロセス設計・検証] B --> E[文書管理・監査] C --> F[検査・測定] C --> G[不適合管理] style A fill:#e8f5e9 style B fill:#c8e6c9 style C fill:#a5d6a7

1.2 プロセス能力評価

コード例1: プロセス能力指数(Cp、Cpk)の計算

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

def calculate_process_capability(data, USL, LSL):
    """
    プロセス能力指数(Cp、Cpk)の計算

    Parameters:
    -----------
    data : array-like
        プロセスデータ(例: 製品純度、寸法)
    USL : float
        Upper Specification Limit(規格上限)
    LSL : float
        Lower Specification Limit(規格下限)

    Returns:
    --------
    dict : プロセス能力指数と統計量
    """
    # 基本統計量
    mean = np.mean(data)
    std = np.std(data, ddof=1)  # 不偏標準偏差

    # Cp(プロセス能力指数)
    # Cp = (USL - LSL) / (6σ)
    Cp = (USL - LSL) / (6 * std)

    # Cpk(プロセス能力指数、片側考慮)
    # Cpk = min((USL - μ) / 3σ, (μ - LSL) / 3σ)
    Cpu = (USL - mean) / (3 * std)
    Cpl = (mean - LSL) / (3 * std)
    Cpk = min(Cpu, Cpl)

    # 不良率の推定(正規分布を仮定)
    defect_rate_upper = 1 - stats.norm.cdf(USL, mean, std)
    defect_rate_lower = stats.norm.cdf(LSL, mean, std)
    total_defect_rate = defect_rate_upper + defect_rate_lower

    return {
        'mean': mean,
        'std': std,
        'Cp': Cp,
        'Cpk': Cpk,
        'Cpu': Cpu,
        'Cpl': Cpl,
        'defect_rate': total_defect_rate,
        'defect_ppm': total_defect_rate * 1e6
    }

# 化学プロセスの製品純度データ(%)
np.random.seed(42)
purity_data = np.random.normal(loc=98.5, scale=0.3, size=200)

# 規格上下限
USL = 99.5  # 規格上限 [%]
LSL = 97.5  # 規格下限 [%]

# プロセス能力計算
capability = calculate_process_capability(purity_data, USL, LSL)

# 可視化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# ヒストグラムとプロセス能力
ax1.hist(purity_data, bins=30, density=True, alpha=0.7, color='#11998e',
         edgecolor='black', label='実測データ')

# 正規分布フィット
x = np.linspace(LSL - 1, USL + 1, 200)
ax1.plot(x, stats.norm.pdf(x, capability['mean'], capability['std']),
         'r-', linewidth=2, label='正規分布フィット')

# 規格限界線
ax1.axvline(USL, color='red', linestyle='--', linewidth=2, label=f'USL = {USL}%')
ax1.axvline(LSL, color='red', linestyle='--', linewidth=2, label=f'LSL = {LSL}%')
ax1.axvline(capability['mean'], color='green', linestyle='-', linewidth=2,
            label=f'平均 = {capability["mean"]:.2f}%')

ax1.set_xlabel('製品純度 [%]', fontsize=11)
ax1.set_ylabel('確率密度', fontsize=11)
ax1.set_title('プロセス能力分布', fontsize=12, fontweight='bold')
ax1.legend(fontsize=9)
ax1.grid(alpha=0.3)

# 能力指数の可視化
indices = ['Cp', 'Cpk', 'Cpu', 'Cpl']
values = [capability[idx] for idx in indices]
colors = ['#11998e' if v >= 1.33 else '#ffa726' if v >= 1.0 else '#ef5350' for v in values]

bars = ax2.bar(indices, values, color=colors, edgecolor='black', linewidth=1.5)
ax2.axhline(y=1.33, color='green', linestyle='--', linewidth=2,
            label='優秀基準 (≥1.33)', alpha=0.7)
ax2.axhline(y=1.00, color='orange', linestyle='--', linewidth=2,
            label='合格基準 (≥1.00)', alpha=0.7)

# 各バーに数値を表示
for bar in bars:
    height = bar.get_height()
    ax2.text(bar.get_x() + bar.get_width()/2., height + 0.05,
             f'{height:.3f}', ha='center', va='bottom', fontsize=10, fontweight='bold')

ax2.set_ylabel('能力指数', fontsize=11)
ax2.set_title('プロセス能力指数', fontsize=12, fontweight='bold')
ax2.legend(fontsize=9)
ax2.grid(alpha=0.3, axis='y')
ax2.set_ylim(0, max(values) * 1.2)

plt.tight_layout()
plt.show()

# 結果出力
print("=" * 60)
print("プロセス能力分析結果")
print("=" * 60)
print(f"平均値:             {capability['mean']:.4f} %")
print(f"標準偏差:           {capability['std']:.4f} %")
print(f"Cp (プロセス能力):  {capability['Cp']:.4f}")
print(f"Cpk (修正能力指数): {capability['Cpk']:.4f}")
print(f"Cpu (上側能力):     {capability['Cpu']:.4f}")
print(f"Cpl (下側能力):     {capability['Cpl']:.4f}")
print(f"推定不良率:         {capability['defect_rate']:.6%}")
print(f"推定不良率 [ppm]:   {capability['defect_ppm']:.2f} ppm")
print("=" * 60)

# 能力評価
if capability['Cpk'] >= 1.33:
    print("✅ 評価: 優秀 - プロセス能力は十分です")
elif capability['Cpk'] >= 1.00:
    print("⚠️  評価: 合格 - プロセス能力は許容範囲ですが改善余地あり")
else:
    print("❌ 評価: 不合格 - プロセス能力が不足、早急な改善が必要")

出力例:

============================================================
プロセス能力分析結果
============================================================
平均値:             98.5041 %
標準偏差:           0.2989 %
Cp (プロセス能力):  1.1163
Cpk (修正能力指数): 1.1107
Cpu (上側能力):     1.1107
Cpl (下側能力):     1.1218
推定不良率:         0.000713%
推定不良率 [ppm]:   7.13 ppm
============================================================
⚠️  評価: 合格 - プロセス能力は許容範囲ですが改善余地あり

解説: プロセス能力指数(Cp、Cpk)は、プロセスが規格を満たす能力を定量評価します。Cp ≥ 1.33なら優秀、Cp ≥ 1.0なら合格とされます。Cpkは平均値の位置も考慮した指標です。


コード例2: パレート分析(80-20ルール)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def pareto_analysis(data_dict, title="パレート図"):
    """
    パレート分析の実行と可視化

    Parameters:
    -----------
    data_dict : dict
        カテゴリ名: 発生件数の辞書
    title : str
        グラフタイトル
    """
    # DataFrameに変換してソート
    df = pd.DataFrame(list(data_dict.items()), columns=['Category', 'Count'])
    df = df.sort_values('Count', ascending=False).reset_index(drop=True)

    # 累積比率の計算
    df['Cumulative'] = df['Count'].cumsum()
    df['Cumulative_Pct'] = 100 * df['Cumulative'] / df['Count'].sum()
    df['Percent'] = 100 * df['Count'] / df['Count'].sum()

    # 可視化
    fig, ax1 = plt.subplots(figsize=(12, 6))

    # 棒グラフ
    x_pos = np.arange(len(df))
    bars = ax1.bar(x_pos, df['Count'], color='#11998e', alpha=0.8,
                   edgecolor='black', linewidth=1.2, label='発生件数')

    ax1.set_xlabel('不良項目', fontsize=11)
    ax1.set_ylabel('発生件数', fontsize=11)
    ax1.set_xticks(x_pos)
    ax1.set_xticklabels(df['Category'], rotation=45, ha='right')

    # 累積比率の線グラフ
    ax2 = ax1.twinx()
    line = ax2.plot(x_pos, df['Cumulative_Pct'], color='red', marker='o',
                    linewidth=2.5, markersize=8, label='累積比率')
    ax2.set_ylabel('累積比率 [%]', fontsize=11)
    ax2.set_ylim(0, 110)
    ax2.axhline(y=80, color='orange', linestyle='--', linewidth=2,
                alpha=0.7, label='80%ライン')

    # 各バーの上に割合を表示
    for i, (bar, pct) in enumerate(zip(bars, df['Percent'])):
        height = bar.get_height()
        ax1.text(bar.get_x() + bar.get_width()/2., height + 0.5,
                f'{pct:.1f}%', ha='center', va='bottom', fontsize=9)

    # 凡例
    lines1, labels1 = ax1.get_legend_handles_labels()
    lines2, labels2 = ax2.get_legend_handles_labels()
    ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left', fontsize=10)

    ax1.set_title(title, fontsize=13, fontweight='bold')
    ax1.grid(alpha=0.3, axis='y')
    plt.tight_layout()
    plt.show()

    return df

# 化学プラントの不良項目データ(1ヶ月間)
defects = {
    '原料不純物混入': 145,
    '温度制御異常': 98,
    '圧力変動': 76,
    '反応時間不足': 54,
    '触媒活性低下': 42,
    '配管詰まり': 28,
    '計測器誤差': 18,
    'pH制御ずれ': 15,
    '冷却不足': 12,
    '撹拌不良': 8,
    '配合比誤差': 6,
    'その他': 4
}

# パレート分析実行
df_pareto = pareto_analysis(defects, title='化学プラント不良要因のパレート分析')

# 80%ラインを超える項目の特定
cumsum_80 = df_pareto[df_pareto['Cumulative_Pct'] <= 80]
print("\n" + "=" * 60)
print("パレート分析結果(80-20ルール)")
print("=" * 60)
print(f"総不良件数: {df_pareto['Count'].sum()} 件\n")
print("重点管理項目(累積80%まで):")
print("-" * 60)
for idx, row in cumsum_80.iterrows():
    print(f"{idx+1}. {row['Category']:<18} "
          f"{row['Count']:>4} 件 ({row['Percent']:>5.1f}%) "
          f"累積: {row['Cumulative_Pct']:>5.1f}%")

print("=" * 60)
print(f"✅ 重点管理すべき項目数: {len(cumsum_80)} / {len(df_pareto)} 項目")
print(f"   これらで全不良の {cumsum_80['Percent'].sum():.1f}% をカバー")

出力例:

============================================================
パレート分析結果(80-20ルール)
============================================================
総不良件数: 506 件

重点管理項目(累積80%まで):
------------------------------------------------------------
1. 原料不純物混入       145 件 (28.7%) 累積:  28.7%
2. 温度制御異常          98 件 (19.4%) 累積:  48.0%
3. 圧力変動              76 件 (15.0%) 累積:  63.0%
4. 反応時間不足          54 件 (10.7%) 累積:  73.7%
============================================================
✅ 重点管理すべき項目数: 4 / 12 項目
   これらで全不良の 73.7% をカバー

解説: パレート分析(80-20ルール)により、「少数の重要要因が問題の大部分を占める」ことを可視化します。上位4項目で全不良の73.7%を占めるため、これらを優先的に改善すべきです。


コード例3: 特性要因図(フィッシュボーン図)のデータ構造

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

def create_fishbone_data(problem, major_causes):
    """
    特性要因図のデータ構造を作成

    Parameters:
    -----------
    problem : str
        品質問題(結果)
    major_causes : dict
        主要因カテゴリとその要因のリスト

    Returns:
    --------
    dict : 特性要因図データ
    """
    return {
        'problem': problem,
        'causes': major_causes
    }

def visualize_fishbone(fishbone_data):
    """
    特性要因図の可視化(簡易版)
    """
    fig, ax = plt.subplots(figsize=(14, 8))

    # 魚の背骨(主軸)
    ax.arrow(0.1, 0.5, 0.7, 0, head_width=0.05, head_length=0.05,
             fc='black', ec='black', linewidth=2)

    # 問題(魚の頭)
    ax.text(0.85, 0.5, fishbone_data['problem'], fontsize=14,
            fontweight='bold', bbox=dict(boxstyle='round',
            facecolor='#ef5350', edgecolor='black', linewidth=2),
            ha='center', va='center')

    # 主要因の配置
    causes = fishbone_data['causes']
    n_causes = len(causes)
    positions = [(0.25, 0.75), (0.45, 0.75), (0.65, 0.75),  # 上側
                 (0.25, 0.25), (0.45, 0.25), (0.65, 0.25)]  # 下側

    for i, (category, factors) in enumerate(causes.items()):
        if i >= len(positions):
            break

        x, y = positions[i]

        # 大骨(カテゴリ)
        if y > 0.5:  # 上側
            ax.plot([x, x], [0.5, y], 'k-', linewidth=2)
            text_y = y + 0.05
        else:  # 下側
            ax.plot([x, x], [0.5, y], 'k-', linewidth=2)
            text_y = y - 0.05

        # カテゴリ名
        ax.text(x, text_y, category, fontsize=11, fontweight='bold',
                bbox=dict(boxstyle='round', facecolor='#11998e',
                         edgecolor='black', alpha=0.8),
                ha='center', va='center')

        # 小骨(要因)- テキストとして表示
        factor_text = '\n'.join([f'• {f}' for f in factors])
        ax.text(x, y, factor_text, fontsize=8, ha='center', va='center',
                bbox=dict(boxstyle='round', facecolor='white',
                         edgecolor='gray', alpha=0.9))

    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)
    ax.axis('off')
    ax.set_title('特性要因図(フィッシュボーン図)', fontsize=14, fontweight='bold')

    plt.tight_layout()
    plt.show()

# 化学プロセスの品質問題分析
fishbone = create_fishbone_data(
    problem='製品純度低下',
    major_causes={
        '原料(Material)': [
            '原料純度不足',
            '不純物混入',
            '保管条件不良'
        ],
        '方法(Method)': [
            '反応時間不足',
            'SOP未遵守',
            '温度制御誤差'
        ],
        '設備(Machine)': [
            '反応器汚染',
            '配管劣化',
            '計測器校正ずれ'
        ],
        '人(Man)': [
            '操作ミス',
            '訓練不足',
            '確認不足'
        ],
        '測定(Measurement)': [
            '分析誤差',
            'サンプリング不良',
            '機器精度不足'
        ],
        '環境(Environment)': [
            '温湿度変動',
            '振動影響',
            '外部汚染'
        ]
    }
)

# 可視化
visualize_fishbone(fishbone)

# データ構造の出力
print("=" * 60)
print("特性要因図データ構造")
print("=" * 60)
print(f"品質問題: {fishbone['problem']}\n")
for category, factors in fishbone['causes'].items():
    print(f"{category}:")
    for factor in factors:
        print(f"  • {factor}")
    print()

解説: 特性要因図(フィッシュボーン図、石川ダイアグラム)は、品質問題の根本原因を体系的に分析する手法です。4M+2E(Man、Machine、Material、Method、Measurement、Environment)のカテゴリで要因を整理します。


コード例4: PDCAサイクルトラッキングシステム

import pandas as pd
from datetime import datetime, timedelta

class PDCACycle:
    """
    PDCAサイクル管理システム
    """
    def __init__(self, project_name):
        self.project_name = project_name
        self.cycles = []

    def add_cycle(self, plan, do, check, act, start_date, cycle_duration_days=30):
        """
        PDCAサイクルを追加

        Parameters:
        -----------
        plan : str
            計画(Plan)
        do : str
            実行(Do)
        check : str
            評価(Check)
        act : str
            改善(Act)
        start_date : str
            開始日(YYYY-MM-DD)
        cycle_duration_days : int
            1サイクルの期間(日数)
        """
        start = datetime.strptime(start_date, '%Y-%m-%d')

        cycle = {
            'cycle_id': len(self.cycles) + 1,
            'plan': plan,
            'do': do,
            'check': check,
            'act': act,
            'start_date': start,
            'end_date': start + timedelta(days=cycle_duration_days),
            'status': 'Planned',
            'kpi_before': None,
            'kpi_after': None,
            'improvement_pct': None
        }

        self.cycles.append(cycle)

    def update_status(self, cycle_id, status, kpi_before=None, kpi_after=None):
        """
        PDCAサイクルのステータス更新
        """
        for cycle in self.cycles:
            if cycle['cycle_id'] == cycle_id:
                cycle['status'] = status
                if kpi_before is not None:
                    cycle['kpi_before'] = kpi_before
                if kpi_after is not None:
                    cycle['kpi_after'] = kpi_after
                    if kpi_before is not None:
                        cycle['improvement_pct'] = 100 * (kpi_after - kpi_before) / kpi_before
                break

    def get_summary(self):
        """
        PDCAサイクル一覧の取得
        """
        df = pd.DataFrame(self.cycles)
        if not df.empty:
            df['start_date'] = df['start_date'].dt.strftime('%Y-%m-%d')
            df['end_date'] = df['end_date'].dt.strftime('%Y-%m-%d')
        return df

    def visualize_progress(self):
        """
        改善進捗の可視化
        """
        df = self.get_summary()

        # KPI改善の可視化
        cycles_with_kpi = df[df['kpi_after'].notna()]

        if len(cycles_with_kpi) == 0:
            print("KPIデータがまだありません")
            return

        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

        # KPI推移
        ax1.plot(cycles_with_kpi['cycle_id'], cycles_with_kpi['kpi_before'],
                marker='o', linewidth=2, markersize=8, label='改善前', color='#ef5350')
        ax1.plot(cycles_with_kpi['cycle_id'], cycles_with_kpi['kpi_after'],
                marker='s', linewidth=2, markersize=8, label='改善後', color='#11998e')
        ax1.set_xlabel('PDCAサイクル番号', fontsize=11)
        ax1.set_ylabel('KPI値', fontsize=11)
        ax1.set_title('PDCA改善のKPI推移', fontsize=12, fontweight='bold')
        ax1.legend(fontsize=10)
        ax1.grid(alpha=0.3)

        # 改善率
        colors = ['#11998e' if x > 0 else '#ef5350'
                  for x in cycles_with_kpi['improvement_pct']]
        bars = ax2.bar(cycles_with_kpi['cycle_id'], cycles_with_kpi['improvement_pct'],
                      color=colors, edgecolor='black', linewidth=1.2)

        # 各バーに改善率を表示
        for bar, pct in zip(bars, cycles_with_kpi['improvement_pct']):
            height = bar.get_height()
            ax2.text(bar.get_x() + bar.get_width()/2., height + 0.5 if height > 0 else height - 0.5,
                    f'{pct:.1f}%', ha='center', va='bottom' if height > 0 else 'top',
                    fontsize=10, fontweight='bold')

        ax2.axhline(y=0, color='black', linestyle='-', linewidth=1)
        ax2.set_xlabel('PDCAサイクル番号', fontsize=11)
        ax2.set_ylabel('改善率 [%]', fontsize=11)
        ax2.set_title('サイクルごとの改善効果', fontsize=12, fontweight='bold')
        ax2.grid(alpha=0.3, axis='y')

        plt.tight_layout()
        plt.show()

# PDCAサイクル管理の実例
pdca = PDCACycle(project_name='製品純度改善プロジェクト')

# サイクル1
pdca.add_cycle(
    plan='原料純度検査基準を95%から98%に引き上げ',
    do='新しい検査基準で原料受入検査を実施(1ヶ月間)',
    check='製品純度が97.8%→98.2%に改善(+0.4%)',
    act='新基準を標準化、サプライヤーにフィードバック',
    start_date='2025-01-01',
    cycle_duration_days=30
)
pdca.update_status(cycle_id=1, status='Completed', kpi_before=97.8, kpi_after=98.2)

# サイクル2
pdca.add_cycle(
    plan='反応温度の制御精度を±2°Cから±0.5°Cに改善',
    do='温度制御システムのPIDパラメータ最適化',
    check='製品純度が98.2%→98.6%に改善(+0.4%)',
    act='最適化したPIDパラメータを全バッチに適用',
    start_date='2025-02-01',
    cycle_duration_days=30
)
pdca.update_status(cycle_id=2, status='Completed', kpi_before=98.2, kpi_after=98.6)

# サイクル3
pdca.add_cycle(
    plan='反応時間を180分から200分に延長(副反応抑制のため)',
    do='反応時間延長を10バッチで試験',
    check='製品純度が98.6%→98.9%に改善(+0.3%)',
    act='標準反応時間を200分に変更、生産計画を調整',
    start_date='2025-03-01',
    cycle_duration_days=30
)
pdca.update_status(cycle_id=3, status='Completed', kpi_before=98.6, kpi_after=98.9)

# サマリー表示
df_summary = pdca.get_summary()
print("=" * 90)
print(f"PDCAサイクル管理: {pdca.project_name}")
print("=" * 90)
print(df_summary[['cycle_id', 'plan', 'status', 'kpi_before', 'kpi_after',
                  'improvement_pct']].to_string(index=False))
print("=" * 90)

# 改善効果の集計
total_improvement = df_summary['kpi_after'].iloc[-1] - df_summary['kpi_before'].iloc[0]
print(f"\n総改善効果: {df_summary['kpi_before'].iloc[0]:.1f}% → "
      f"{df_summary['kpi_after'].iloc[-1]:.1f}% (+{total_improvement:.1f}%)")

# 進捗可視化
pdca.visualize_progress()

解説: PDCAサイクル(Plan-Do-Check-Act)は、継続的改善の基本フレームワークです。各サイクルでKPIを測定し、改善効果を定量的に評価することが重要です。


コード例5: 品質コスト分析(COQ: Cost of Quality)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

class QualityCostAnalyzer:
    """
    品質コスト分析ツール(COQ分析)
    """
    def __init__(self):
        self.cost_data = {
            'prevention': [],      # 予防コスト
            'appraisal': [],       # 評価コスト
            'internal_failure': [], # 内部失敗コスト
            'external_failure': []  # 外部失敗コスト
        }

    def add_cost(self, category, description, amount):
        """
        品質コストを追加

        Parameters:
        -----------
        category : str
            コストカテゴリ(prevention, appraisal, internal_failure, external_failure)
        description : str
            コスト内容
        amount : float
            金額(円)
        """
        if category in self.cost_data:
            self.cost_data[category].append({
                'description': description,
                'amount': amount
            })
        else:
            raise ValueError(f"無効なカテゴリ: {category}")

    def calculate_totals(self):
        """
        カテゴリ別・総コストの計算
        """
        totals = {}
        for category, items in self.cost_data.items():
            totals[category] = sum(item['amount'] for item in items)

        totals['total_prevention_appraisal'] = totals['prevention'] + totals['appraisal']
        totals['total_failure'] = totals['internal_failure'] + totals['external_failure']
        totals['total'] = totals['total_prevention_appraisal'] + totals['total_failure']

        return totals

    def visualize(self):
        """
        品質コストの可視化
        """
        totals = self.calculate_totals()

        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

        # カテゴリ別コスト(円グラフ)
        categories = ['予防コスト', '評価コスト', '内部失敗コスト', '外部失敗コスト']
        amounts = [totals['prevention'], totals['appraisal'],
                   totals['internal_failure'], totals['external_failure']]
        colors = ['#11998e', '#38ef7d', '#ffa726', '#ef5350']

        wedges, texts, autotexts = ax1.pie(amounts, labels=categories, autopct='%1.1f%%',
                                             colors=colors, startangle=90,
                                             textprops={'fontsize': 10})
        for autotext in autotexts:
            autotext.set_color('white')
            autotext.set_fontweight('bold')

        ax1.set_title('品質コストの内訳', fontsize=12, fontweight='bold')

        # PAF比率分析(Prevention-Appraisal-Failure)
        paf_categories = ['予防・評価\nコスト', '失敗コスト']
        paf_amounts = [totals['total_prevention_appraisal'], totals['total_failure']]
        paf_colors = ['#11998e', '#ef5350']

        bars = ax2.bar(paf_categories, paf_amounts, color=paf_colors,
                      edgecolor='black', linewidth=1.5)

        # 各バーに金額と比率を表示
        for bar, amount in zip(bars, paf_amounts):
            height = bar.get_height()
            pct = 100 * amount / totals['total']
            ax2.text(bar.get_x() + bar.get_width()/2., height + 5,
                    f'¥{amount:,.0f}\n({pct:.1f}%)', ha='center', va='bottom',
                    fontsize=10, fontweight='bold')

        ax2.set_ylabel('コスト [円]', fontsize=11)
        ax2.set_title('PAF比率分析', fontsize=12, fontweight='bold')
        ax2.grid(alpha=0.3, axis='y')

        plt.tight_layout()
        plt.show()

    def get_summary(self):
        """
        コストサマリーの取得
        """
        totals = self.calculate_totals()

        # 各カテゴリの詳細
        details = []
        for category, items in self.cost_data.items():
            for item in items:
                details.append({
                    'カテゴリ': category,
                    '内容': item['description'],
                    '金額': item['amount']
                })

        return pd.DataFrame(details), totals

# 品質コスト分析の実例
coq = QualityCostAnalyzer()

# 予防コスト(Prevention Costs)
coq.add_cost('prevention', '品質計画策定', 500000)
coq.add_cost('prevention', '設備予防保全', 1200000)
coq.add_cost('prevention', '従業員訓練', 800000)
coq.add_cost('prevention', 'プロセス改善活動', 600000)

# 評価コスト(Appraisal Costs)
coq.add_cost('appraisal', '受入検査', 900000)
coq.add_cost('appraisal', '工程内検査', 1500000)
coq.add_cost('appraisal', '最終製品検査', 1100000)
coq.add_cost('appraisal', '測定機器校正', 400000)

# 内部失敗コスト(Internal Failure Costs)
coq.add_cost('internal_failure', '不良品廃棄', 2800000)
coq.add_cost('internal_failure', '手直し・再加工', 1900000)
coq.add_cost('internal_failure', 'ダウングレード品', 700000)
coq.add_cost('internal_failure', '再検査', 500000)

# 外部失敗コスト(External Failure Costs)
coq.add_cost('external_failure', '顧客クレーム対応', 1200000)
coq.add_cost('external_failure', '製品リコール', 800000)
coq.add_cost('external_failure', '保証修理', 600000)
coq.add_cost('external_failure', 'ブランドイメージ損失', 400000)

# サマリー表示
df_details, totals = coq.get_summary()

print("=" * 70)
print("品質コスト分析結果(COQ: Cost of Quality)")
print("=" * 70)
print("\nカテゴリ別コスト:")
print("-" * 70)
print(f"予防コスト (Prevention):         ¥{totals['prevention']:>12,.0f}")
print(f"評価コスト (Appraisal):          ¥{totals['appraisal']:>12,.0f}")
print(f"内部失敗コスト (Internal Failure): ¥{totals['internal_failure']:>12,.0f}")
print(f"外部失敗コスト (External Failure): ¥{totals['external_failure']:>12,.0f}")
print("-" * 70)
print(f"総品質コスト:                    ¥{totals['total']:>12,.0f}")
print("=" * 70)

# PAF比率の分析
paf_ratio = totals['total_prevention_appraisal'] / totals['total_failure']
print(f"\nPAF比率(予防・評価 / 失敗): {paf_ratio:.2f}")

if paf_ratio < 0.5:
    print("⚠️  失敗コストが高すぎます。予防・評価活動への投資を増やすべきです。")
elif paf_ratio < 1.0:
    print("⚠️  失敗コストがやや高めです。予防活動の強化を検討してください。")
else:
    print("✅ 適切なバランスです。予防的品質管理が機能しています。")

# 可視化
coq.visualize()

# 詳細データ
print("\n品質コスト詳細:")
print(df_details.to_string(index=False))

解説: 品質コスト(COQ)は、予防コスト、評価コスト、失敗コスト(内部・外部)の4つに分類されます。失敗コストが高い場合、予防・評価活動への投資を増やすことで、総コストを削減できる可能性があります。


コード例6: 不良率計算と信頼区間

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

def calculate_defect_rate_ci(n_defects, n_total, confidence=0.95):
    """
    不良率と信頼区間の計算(二項分布)

    Parameters:
    -----------
    n_defects : int
        不良品数
    n_total : int
        検査総数
    confidence : float
        信頼水準(デフォルト: 0.95 = 95%)

    Returns:
    --------
    dict : 不良率、信頼区間、PPM
    """
    # 不良率
    p_defect = n_defects / n_total

    # 信頼区間(正規近似、大標本の場合)
    z = stats.norm.ppf((1 + confidence) / 2)
    se = np.sqrt(p_defect * (1 - p_defect) / n_total)

    ci_lower = max(0, p_defect - z * se)
    ci_upper = min(1, p_defect + z * se)

    # Wilson score interval(小標本でも精度が高い)
    denominator = 1 + z**2 / n_total
    center = (p_defect + z**2 / (2 * n_total)) / denominator
    margin = z * np.sqrt(p_defect * (1 - p_defect) / n_total + z**2 / (4 * n_total**2)) / denominator

    wilson_lower = max(0, center - margin)
    wilson_upper = min(1, center + margin)

    return {
        'defect_rate': p_defect,
        'defect_pct': p_defect * 100,
        'defect_ppm': p_defect * 1e6,
        'ci_lower': ci_lower,
        'ci_upper': ci_upper,
        'ci_lower_ppm': ci_lower * 1e6,
        'ci_upper_ppm': ci_upper * 1e6,
        'wilson_lower': wilson_lower,
        'wilson_upper': wilson_upper,
        'wilson_lower_ppm': wilson_lower * 1e6,
        'wilson_upper_ppm': wilson_upper * 1e6,
        'n_defects': n_defects,
        'n_total': n_total,
        'confidence': confidence
    }

def compare_defect_rates(n1_defects, n1_total, n2_defects, n2_total, alpha=0.05):
    """
    2つの不良率の比較(統計的検定)

    Parameters:
    -----------
    n1_defects, n1_total : int
        グループ1の不良品数と総数
    n2_defects, n2_total : int
        グループ2の不良品数と総数
    alpha : float
        有意水準(デフォルト: 0.05 = 5%)

    Returns:
    --------
    dict : 検定結果
    """
    p1 = n1_defects / n1_total
    p2 = n2_defects / n2_total

    # プール推定値
    p_pooled = (n1_defects + n2_defects) / (n1_total + n2_total)

    # 標準誤差
    se = np.sqrt(p_pooled * (1 - p_pooled) * (1/n1_total + 1/n2_total))

    # z統計量
    z_stat = (p1 - p2) / se
    p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))

    return {
        'p1': p1,
        'p2': p2,
        'p1_ppm': p1 * 1e6,
        'p2_ppm': p2 * 1e6,
        'difference': p1 - p2,
        'difference_ppm': (p1 - p2) * 1e6,
        'z_statistic': z_stat,
        'p_value': p_value,
        'significant': p_value < alpha,
        'alpha': alpha
    }

# 不良率計算の例
n_defects = 45
n_total = 5000

result = calculate_defect_rate_ci(n_defects, n_total, confidence=0.95)

print("=" * 70)
print("不良率分析結果")
print("=" * 70)
print(f"検査総数:           {result['n_total']:,} 個")
print(f"不良品数:           {result['n_defects']:,} 個")
print(f"不良率:             {result['defect_pct']:.3f}%")
print(f"不良率 [ppm]:       {result['defect_ppm']:.1f} ppm")
print(f"\n95%信頼区間:")
print(f"  下限:             {result['ci_lower']*100:.3f}% ({result['ci_lower_ppm']:.1f} ppm)")
print(f"  上限:             {result['ci_upper']*100:.3f}% ({result['ci_upper_ppm']:.1f} ppm)")
print(f"\nWilson信頼区間(推奨):")
print(f"  下限:             {result['wilson_lower']*100:.3f}% ({result['wilson_lower_ppm']:.1f} ppm)")
print(f"  上限:             {result['wilson_upper']*100:.3f}% ({result['wilson_upper_ppm']:.1f} ppm)")
print("=" * 70)

# 改善前後の不良率比較
print("\n" + "=" * 70)
print("改善効果の統計的検証")
print("=" * 70)

# 改善前
n1_defects = 45
n1_total = 5000

# 改善後
n2_defects = 28
n2_total = 5000

comparison = compare_defect_rates(n1_defects, n1_total, n2_defects, n2_total, alpha=0.05)

print(f"改善前 不良率:     {comparison['p1_ppm']:.1f} ppm")
print(f"改善後 不良率:     {comparison['p2_ppm']:.1f} ppm")
print(f"改善効果:          {-comparison['difference_ppm']:.1f} ppm ({-comparison['difference']*100:.3f}%)")
print(f"\n統計的検定:")
print(f"  z統計量:         {comparison['z_statistic']:.3f}")
print(f"  p値:             {comparison['p_value']:.4f}")
print(f"  有意水準:        {comparison['alpha']}")

if comparison['significant']:
    print(f"✅ 結論: 改善効果は統計的に有意です(p < {comparison['alpha']})")
else:
    print(f"⚠️  結論: 改善効果は統計的に有意ではありません(p >= {comparison['alpha']})")

# 可視化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# 不良率の信頼区間
categories = ['改善前', '改善後']
rates = [comparison['p1_ppm'], comparison['p2_ppm']]
ci_lower_before = calculate_defect_rate_ci(n1_defects, n1_total)['wilson_lower_ppm']
ci_upper_before = calculate_defect_rate_ci(n1_defects, n1_total)['wilson_upper_ppm']
ci_lower_after = calculate_defect_rate_ci(n2_defects, n2_total)['wilson_lower_ppm']
ci_upper_after = calculate_defect_rate_ci(n2_defects, n2_total)['wilson_upper_ppm']

errors = [
    [rates[0] - ci_lower_before, ci_upper_before - rates[0]],
    [rates[1] - ci_lower_after, ci_upper_after - rates[1]]
]

bars = ax1.bar(categories, rates, yerr=np.array(errors).T, capsize=10,
              color=['#ef5350', '#11998e'], edgecolor='black', linewidth=1.5)

for bar, rate in zip(bars, rates):
    height = bar.get_height()
    ax1.text(bar.get_x() + bar.get_width()/2., height + 0.5,
            f'{rate:.1f} ppm', ha='center', va='bottom', fontsize=11, fontweight='bold')

ax1.set_ylabel('不良率 [ppm]', fontsize=11)
ax1.set_title('改善前後の不良率比較(95%信頼区間)', fontsize=12, fontweight='bold')
ax1.grid(alpha=0.3, axis='y')

# 不良品数の推移(架空の時系列データ)
months = np.arange(1, 13)
defects_before = np.random.poisson(9, 6)  # 改善前(平均9個/月)
defects_after = np.random.poisson(5.6, 6)  # 改善後(平均5.6個/月)
defects_trend = np.concatenate([defects_before, defects_after])

ax2.plot(months, defects_trend, marker='o', linewidth=2, markersize=8, color='#11998e')
ax2.axvline(x=6.5, color='red', linestyle='--', linewidth=2, label='改善実施')
ax2.fill_between(months[:6], 0, 20, alpha=0.1, color='#ef5350', label='改善前')
ax2.fill_between(months[6:], 0, 20, alpha=0.1, color='#11998e', label='改善後')

ax2.set_xlabel('月', fontsize=11)
ax2.set_ylabel('不良品数 [個/月]', fontsize=11)
ax2.set_title('不良品数の推移', fontsize=12, fontweight='bold')
ax2.legend(fontsize=10)
ax2.grid(alpha=0.3)

plt.tight_layout()
plt.show()

解説: 不良率の評価には信頼区間の計算が重要です。Wilson信頼区間は小標本でも精度が高く推奨されます。改善効果の検証には、統計的仮説検定(z検定)を用いて有意性を確認します。


コード例7: 5回のなぜ(5 Why分析)

class FiveWhyAnalysis:
    """
    5回のなぜ(5 Why)分析ツール
    """
    def __init__(self, problem):
        self.problem = problem
        self.whys = []
        self.root_cause = None
        self.corrective_actions = []

    def add_why(self, question, answer):
        """
        「なぜ」の追加

        Parameters:
        -----------
        question : str
            なぜ?という質問
        answer : str
            その回答(次の原因)
        """
        self.whys.append({
            'level': len(self.whys) + 1,
            'question': question,
            'answer': answer
        })

    def set_root_cause(self, root_cause):
        """
        根本原因の設定
        """
        self.root_cause = root_cause

    def add_corrective_action(self, action, responsible, deadline):
        """
        是正措置の追加

        Parameters:
        -----------
        action : str
            是正措置内容
        responsible : str
            責任者
        deadline : str
            期限
        """
        self.corrective_actions.append({
            'action': action,
            'responsible': responsible,
            'deadline': deadline
        })

    def visualize(self):
        """
        5 Why分析の可視化
        """
        print("=" * 80)
        print("5回のなぜ(5 Why)分析")
        print("=" * 80)
        print(f"問題: {self.problem}\n")

        for why in self.whys:
            print(f"なぜ{why['level']}: {why['question']}")
            print(f"→ {why['answer']}\n")

        if self.root_cause:
            print(f"🎯 根本原因: {self.root_cause}\n")

        if self.corrective_actions:
            print("-" * 80)
            print("是正措置(Corrective Actions):")
            print("-" * 80)
            for i, action in enumerate(self.corrective_actions, 1):
                print(f"{i}. {action['action']}")
                print(f"   責任者: {action['responsible']} | 期限: {action['deadline']}\n")

        print("=" * 80)

# 5 Why分析の実例
analysis = FiveWhyAnalysis(problem='製品純度が規格下限を下回った(97.2%、規格: ≥97.5%)')

analysis.add_why(
    question='なぜ製品純度が低いのか?',
    answer='反応温度が目標値(185°C)より低かった(180°C)'
)

analysis.add_why(
    question='なぜ反応温度が低かったのか?',
    answer='温度センサーの読み値が実際より5°C高く表示されていた'
)

analysis.add_why(
    question='なぜ温度センサーの読み値がずれていたのか?',
    answer='温度センサーの校正が実施されていなかった'
)

analysis.add_why(
    question='なぜ温度センサーの校正が実施されていなかったのか?',
    answer='校正スケジュールが管理されておらず、期限切れに気づかなかった'
)

analysis.add_why(
    question='なぜ校正スケジュールが管理されていなかったのか?',
    answer='計測器管理システム(保守管理台帳)が整備されていなかった'
)

analysis.set_root_cause(
    '計測器管理システムの不備により、校正期限の管理ができていなかった'
)

# 是正措置の追加
analysis.add_corrective_action(
    action='計測器管理台帳(Excelベース)を作成し、全計測器の校正期限を登録',
    responsible='品質保証課 田中',
    deadline='2025-11-15'
)

analysis.add_corrective_action(
    action='校正期限1ヶ月前に自動アラートメールを送信する仕組みを構築',
    responsible='生産技術課 佐藤',
    deadline='2025-11-30'
)

analysis.add_corrective_action(
    action='全温度センサー(12台)の緊急校正を実施',
    responsible='保全課 鈴木',
    deadline='2025-11-10'
)

analysis.add_corrective_action(
    action='毎月の品質会議で計測器校正状況をレビューする手順を追加',
    responsible='品質保証課 田中',
    deadline='2025-12-01'
)

# 分析結果の表示
analysis.visualize()

# 5 Why分析のフローチャート(Mermaid)
print("\n5 Why分析フローチャート:")
print("""
```mermaid
graph TD
    A[問題: 製品純度低下 97.2%] --> B[なぜ1: 反応温度が低い 180°C]
    B --> C[なぜ2: センサー読み値がずれている +5°C誤差]
    C --> D[なぜ3: センサー校正が未実施]
    D --> E[なぜ4: 校正スケジュール未管理]
    E --> F[なぜ5: 計測器管理システム不備]
    F --> G[🎯 根本原因: 管理システム整備不足]

    G --> H[是正措置1: 管理台帳作成]
    G --> I[是正措置2: 自動アラート]
    G --> J[是正措置3: 緊急校正]
    G --> K[是正措置4: 定期レビュー]

    style A fill:#ef5350
    style G fill:#11998e
    style H fill:#c8e6c9
    style I fill:#c8e6c9
    style J fill:#c8e6c9
    style K fill:#c8e6c9
```
""")

解説: 5回のなぜ(5 Why)分析は、問題の表面的な原因ではなく、根本原因を特定する手法です。「なぜ」を繰り返すことで、管理システムやプロセスレベルの問題を発見できます。


コード例8: 品質メトリクスダッシュボード

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

class QualityMetricsDashboard:
    """
    品質管理ダッシュボード
    """
    def __init__(self):
        self.metrics = {
            'dates': [],
            'yield': [],           # 収率 [%]
            'purity': [],          # 純度 [%]
            'defect_rate': [],     # 不良率 [ppm]
            'first_pass_yield': [], # 初回合格率 [%]
            'customer_complaints': [] # 顧客クレーム件数
        }

    def add_daily_metrics(self, date, yield_pct, purity, defect_ppm, fpy, complaints):
        """
        日次品質メトリクスの追加
        """
        self.metrics['dates'].append(date)
        self.metrics['yield'].append(yield_pct)
        self.metrics['purity'].append(purity)
        self.metrics['defect_rate'].append(defect_ppm)
        self.metrics['first_pass_yield'].append(fpy)
        self.metrics['customer_complaints'].append(complaints)

    def calculate_kpis(self):
        """
        KPIの計算
        """
        df = pd.DataFrame(self.metrics)

        kpis = {
            'avg_yield': df['yield'].mean(),
            'avg_purity': df['purity'].mean(),
            'avg_defect_rate': df['defect_rate'].mean(),
            'avg_fpy': df['first_pass_yield'].mean(),
            'total_complaints': df['customer_complaints'].sum(),
            'yield_std': df['yield'].std(),
            'purity_std': df['purity'].std()
        }

        return kpis

    def visualize_dashboard(self):
        """
        品質ダッシュボードの可視化
        """
        df = pd.DataFrame(self.metrics)
        kpis = self.calculate_kpis()

        fig = plt.figure(figsize=(16, 10))
        gs = fig.add_gridspec(3, 3, hspace=0.3, wspace=0.3)

        # 1. 収率の推移
        ax1 = fig.add_subplot(gs[0, 0])
        ax1.plot(df['dates'], df['yield'], marker='o', linewidth=2, color='#11998e')
        ax1.axhline(y=kpis['avg_yield'], color='red', linestyle='--', linewidth=1.5,
                   label=f'平均: {kpis["avg_yield"]:.1f}%')
        ax1.set_ylabel('収率 [%]', fontsize=10)
        ax1.set_title('収率の推移', fontsize=11, fontweight='bold')
        ax1.legend(fontsize=8)
        ax1.grid(alpha=0.3)
        ax1.tick_params(axis='x', rotation=45)

        # 2. 純度の推移
        ax2 = fig.add_subplot(gs[0, 1])
        ax2.plot(df['dates'], df['purity'], marker='s', linewidth=2, color='#38ef7d')
        ax2.axhline(y=kpis['avg_purity'], color='red', linestyle='--', linewidth=1.5,
                   label=f'平均: {kpis["avg_purity"]:.2f}%')
        ax2.axhline(y=97.5, color='orange', linestyle='--', linewidth=1.5, alpha=0.7,
                   label='規格下限: 97.5%')
        ax2.set_ylabel('純度 [%]', fontsize=10)
        ax2.set_title('製品純度の推移', fontsize=11, fontweight='bold')
        ax2.legend(fontsize=8)
        ax2.grid(alpha=0.3)
        ax2.tick_params(axis='x', rotation=45)

        # 3. 不良率の推移
        ax3 = fig.add_subplot(gs[0, 2])
        ax3.plot(df['dates'], df['defect_rate'], marker='^', linewidth=2, color='#ffa726')
        ax3.axhline(y=kpis['avg_defect_rate'], color='red', linestyle='--', linewidth=1.5,
                   label=f'平均: {kpis["avg_defect_rate"]:.0f} ppm')
        ax3.set_ylabel('不良率 [ppm]', fontsize=10)
        ax3.set_title('不良率の推移', fontsize=11, fontweight='bold')
        ax3.legend(fontsize=8)
        ax3.grid(alpha=0.3)
        ax3.tick_params(axis='x', rotation=45)

        # 4. 初回合格率(FPY)
        ax4 = fig.add_subplot(gs[1, 0])
        ax4.plot(df['dates'], df['first_pass_yield'], marker='D', linewidth=2, color='#42a5f5')
        ax4.axhline(y=kpis['avg_fpy'], color='red', linestyle='--', linewidth=1.5,
                   label=f'平均: {kpis["avg_fpy"]:.1f}%')
        ax4.set_ylabel('初回合格率 [%]', fontsize=10)
        ax4.set_title('初回合格率(FPY)の推移', fontsize=11, fontweight='bold')
        ax4.legend(fontsize=8)
        ax4.grid(alpha=0.3)
        ax4.tick_params(axis='x', rotation=45)

        # 5. 顧客クレーム件数
        ax5 = fig.add_subplot(gs[1, 1])
        ax5.bar(df['dates'], df['customer_complaints'], color='#ef5350',
               edgecolor='black', linewidth=0.8)
        ax5.set_ylabel('クレーム件数', fontsize=10)
        ax5.set_title('顧客クレーム件数', fontsize=11, fontweight='bold')
        ax5.grid(alpha=0.3, axis='y')
        ax5.tick_params(axis='x', rotation=45)

        # 6. KPIサマリー(テキスト表示)
        ax6 = fig.add_subplot(gs[1, 2])
        ax6.axis('off')
        kpi_text = f"""
品質KPIサマリー

収率:
  平均: {kpis['avg_yield']:.1f}%
  標準偏差: {kpis['yield_std']:.2f}%

純度:
  平均: {kpis['avg_purity']:.2f}%
  標準偏差: {kpis['purity_std']:.3f}%

不良率:
  平均: {kpis['avg_defect_rate']:.0f} ppm

初回合格率:
  平均: {kpis['avg_fpy']:.1f}%

顧客クレーム:
  総件数: {int(kpis['total_complaints'])} 件
        """
        ax6.text(0.1, 0.5, kpi_text, fontsize=10, verticalalignment='center',
                family='monospace', bbox=dict(boxstyle='round', facecolor='#e8f5e9',
                                              edgecolor='black', linewidth=1.5))

        # 7. 収率・純度の散布図
        ax7 = fig.add_subplot(gs[2, :2])
        scatter = ax7.scatter(df['yield'], df['purity'], c=df['defect_rate'],
                             cmap='RdYlGn_r', s=100, edgecolor='black', linewidth=1)
        ax7.set_xlabel('収率 [%]', fontsize=10)
        ax7.set_ylabel('純度 [%]', fontsize=10)
        ax7.set_title('収率 vs 純度(色: 不良率)', fontsize=11, fontweight='bold')
        cbar = plt.colorbar(scatter, ax=ax7)
        cbar.set_label('不良率 [ppm]', fontsize=9)
        ax7.grid(alpha=0.3)

        # 8. 品質トレンド(移動平均)
        ax8 = fig.add_subplot(gs[2, 2])
        window = 3
        ma_purity = df['purity'].rolling(window=window).mean()
        ax8.plot(df['dates'], df['purity'], 'o-', linewidth=1, alpha=0.5,
                label='実測値', color='gray')
        ax8.plot(df['dates'], ma_purity, linewidth=2.5, label=f'{window}日移動平均',
                color='#11998e')
        ax8.set_ylabel('純度 [%]', fontsize=10)
        ax8.set_title('純度トレンド(移動平均)', fontsize=11, fontweight='bold')
        ax8.legend(fontsize=8)
        ax8.grid(alpha=0.3)
        ax8.tick_params(axis='x', rotation=45)

        plt.suptitle('品質管理ダッシュボード', fontsize=14, fontweight='bold', y=0.995)
        plt.tight_layout()
        plt.show()

# ダッシュボードの作成(30日間のデータ)
dashboard = QualityMetricsDashboard()

np.random.seed(42)
start_date = datetime(2025, 10, 1)

for i in range(30):
    date = start_date + timedelta(days=i)

    # 品質メトリクスのシミュレーション
    yield_pct = np.random.normal(92.5, 1.5)
    purity = np.random.normal(98.2, 0.4)
    defect_ppm = np.random.poisson(850)
    fpy = np.random.normal(94.5, 2.0)
    complaints = np.random.poisson(1.2)

    dashboard.add_daily_metrics(
        date=date.strftime('%m/%d'),
        yield_pct=yield_pct,
        purity=purity,
        defect_ppm=defect_ppm,
        fpy=fpy,
        complaints=complaints
    )

# ダッシュボード表示
dashboard.visualize_dashboard()

# KPIサマリー
kpis = dashboard.calculate_kpis()
print("=" * 60)
print("品質管理 KPIサマリー(30日間)")
print("=" * 60)
print(f"平均収率:           {kpis['avg_yield']:.2f}% ± {kpis['yield_std']:.2f}%")
print(f"平均純度:           {kpis['avg_purity']:.3f}% ± {kpis['purity_std']:.3f}%")
print(f"平均不良率:         {kpis['avg_defect_rate']:.0f} ppm")
print(f"平均初回合格率:     {kpis['avg_fpy']:.2f}%")
print(f"総顧客クレーム:     {int(kpis['total_complaints'])} 件")
print("=" * 60)

解説: 品質メトリクスダッシュボードにより、収率、純度、不良率、初回合格率(FPY)、顧客クレーム件数など、複数の品質指標を統合的に可視化・管理できます。移動平均や相関分析により、品質トレンドを把握します。


1.3 本章のまとめ

学んだこと

  1. 品質管理の基本概念
    • QC、QA、QMSの違いと役割
    • 品質管理の発展(検査 → SPC → TQM)
  2. プロセス能力評価
    • Cp、Cpkによる定量的評価
    • 不良率の推定と信頼区間
  3. 品質改善手法
    • パレート分析による重点管理項目の特定
    • 特性要因図(フィッシュボーン図)による根本原因分析
    • 5回のなぜ分析
  4. TQMと継続的改善
    • PDCAサイクルの実践
    • 品質コスト(COQ)分析
    • 品質メトリクスの統合管理

重要なポイント

次の章へ

第2章では、統計的プロセス管理(SPC)を詳しく学びます:

免責事項