#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()
