見出し画像

#17 Pythonで始めるF検定ver2、チャレンジ AI×100業務(製造業)

データの散らばり具合」に注目するF検定です。

以前、このシリーズで生成したGUIでは計算結果(p値)のみを示すものでしたが、これに箱ひげ図を合わせると、バラツキ具合がより視覚的になりわかりやすくなりました。


それでは、スタートです。
*執筆者は以下を参照してください。


使ったツール・準備したこと

  • Visual Studio Code環境下でのPython

やってみたこと|コード・ステップ紹介

実行した内容の簡単な流れ

ChatGPT 4oへのプロンプト:

F検定のアウトプットとして計算結果の下に、横向きの箱ひげ図を描画してください。

計算結果とともに、箱ひげ図が描画され、バラツキに具合がよくわかります。*有意差はありません。

平均値を比較する場合でも、データの分析の流れは;
・正規性の検定
・F検定
・t検定
の流れになります。上の計算結果見ると、バラツキに有意性は認められませんが、グラフから平均値に差がありそうなことがわかります(t検定で有意なので有意差が認められます)。
*バラツキに有意差がある場合は、平均値の比較には注意が必要です。

今後の展開・アイデア

次回取り組みたいこと

・ランダムフォレスト再び!

■ 今日のコード

import matplotlib
matplotlib.rcParams['font.family'] = 'Meiryo'  # Windows の場合
import tkinter as tk
from tkinter import messagebox
import re
from scipy import stats
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

def run_f_test():
    try:
        raw_data1 = entry_data1.get("1.0", tk.END)
        raw_data2 = entry_data2.get("1.0", tk.END)

        cleaned_data1 = re.sub(r"[\s\n\t]+", ",", raw_data1.strip())
        cleaned_data2 = re.sub(r"[\s\n\t]+", ",", raw_data2.strip())

        data1 = [float(x) for x in cleaned_data1.split(',') if x.strip() != '']
        data2 = [float(x) for x in cleaned_data2.split(',') if x.strip() != '']

        if len(data1) < 2 or len(data2) < 2:
            messagebox.showerror("エラー", "両方の群に2点以上のデータを入力してください。")
            return
        if len(data1) > 30 or len(data2) > 30:
            messagebox.showerror("エラー", "各群のデータは最大30点までです。")
            return

        # 正規性検定(Shapiro-Wilk)
        p_norm1 = stats.shapiro(data1).pvalue
        p_norm2 = stats.shapiro(data2).pvalue

        norm_text = f"正規性p値(群1): {p_norm1:.3f}\n正規性p値(群2): {p_norm2:.3f}"

        # F検定(分散の比)
        var1 = np.var(data1, ddof=1)
        var2 = np.var(data2, ddof=1)
        f = var1 / var2 if var1 > var2 else var2 / var1
        dfn = len(data1) - 1 if var1 > var2 else len(data2) - 1
        dfd = len(data2) - 1 if var1 > var2 else len(data1) - 1
        p_f = 1 - stats.f.cdf(f, dfn, dfd)

        # 非正規分布でも使えるLevene検定
        _, p_levene = stats.levene(data1, data2)

        result_text = f"F検定p値(正規性前提): {p_f:.3f}\nLevene検定p値(非正規対応): {p_levene:.3f}"

        label_result.config(text=f"{norm_text}\n\n{result_text}")

        # 箱ひげ図を描画
        fig, ax = plt.subplots(figsize=(6, 4.5))
        ax.boxplot([data1, data2], vert=False, labels=["群1", "群2"])
        ax.set_title("横向き箱ひげ図")
        ax.set_xlabel("値")

        # 既存のキャンバスを削除してから再描画(重複防止)
        global canvas
        if canvas:
            canvas.get_tk_widget().destroy()
        canvas = FigureCanvasTkAgg(fig, master=root)
        canvas.draw()
        canvas.get_tk_widget().pack()

    except ValueError:
        messagebox.showerror("入力エラー", "数値を正しく入力してください。")

canvas = None

root = tk.Tk()
root.title("F検定アプリ(正規性検定付き)")
root.geometry("600x700")

# データ入力欄1
tk.Label(root, text="群1のデータ(エクセルの列を貼り付け可能、最大30点):").pack()
entry_data1 = tk.Text(root, height=5, width=50)
entry_data1.pack()

# データ入力欄2
tk.Label(root, text="群2のデータ(エクセルの列を貼り付け可能、最大30点):").pack()
entry_data2 = tk.Text(root, height=5, width=50)
entry_data2.pack()

# 計算ボタン
btn_calc = tk.Button(root, text="F検定を実行", command=run_f_test)
btn_calc.pack(pady=10)

# 結果表示
label_result = tk.Label(root, text="", justify="left")
label_result.pack()

root.mainloop()

いいなと思ったら応援しよう!