#12 Pythonで始めるF検定 *バラツキを検定する
カイゼンによる成果;前後の測定値のバラツキには差があるのでしょうか? 目に見える平均値の変化だけでなく、「データの散らばり具合」にも注目することで、改善の効果をより深く理解できるかもしれません。
今回のテーマは「F検定」です。
t検定と同様、統計ソフトはもちろんのこと、エクセルでも検定は可能ですが、ここでは、比べる数値を入力すれば判断できる利点からアプリを作成します。
それでは、スタートです。
*執筆者は以下を参照してください。
使ったツール・準備したこと
Visual Studio Code環境下でのPython
やってみたこと|コード・ステップ紹介
実行した内容の簡単な流れ
ChatGPT 4oへのプロンプト;
t検定アプリと同様にF検定アプリを生成してください。その中には、正規性の検定も含めてください。F検定の出力は、正規分布の場合、そうでない場合の検定の両方のp値を表示してください。
試しに検定してみると・・・
t検定の際と同様に、データが正規分布か否かの検定も入れています(Shapiro-Wilk検定)。また、正規分布でない場合のデータも想定したバラツキの検定も入れています。それぞれp値が計算されていることがわかります。*今回の場合は、有意性は認められませんでした。

今後の展開・アイデア
次回取り組みたいこと
・Feloを触ってみます。
■ 今日のコード
import tkinter as tk
from tkinter import messagebox
import re
from scipy import stats
import numpy as np
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}")
except ValueError:
messagebox.showerror("入力エラー", "数値を正しく入力してください。")
root = tk.Tk()
root.title("F検定アプリ(正規性検定付き)")
root.geometry("500x550")
# データ入力欄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()