見出し画像

#31 Pythonで実施する統計的検定、チャレンジ AI×100業務(製造業)

あるグループのデータ群の平均に差はあるのでしょうか?
平均値に差があるかどうかの検定に至るまでには、いくつかステップがあります。データは正規分布に従うのか?2群のデータのバラツキに有意性は認められるのか?などです。

今日は、チャレンジ#10チャレンジ#11で実施した、t検定、F検定など、まとめて実施できるようにしてみました。


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


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

  • ChatGPT 4o

  • Visual Studio Code環境下でのPython

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

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

ChatGPT 4o;以下を会話しました。

アプリを生成してください。*Pythonで ・データは2群、n=30まで入力可能(エクセルからのコピペOK)
・正規性の検定を実施(表示はp値)
・F検定を実施(正規分布、非正規分布の場合両方)
・F検定で有意差がない場合;等分散を仮定としてt検定を実施(表示はp値)
・F検定で有意差がある場合;等分散を仮定としないt検定を実施(表示はp値)
・グラフは箱ひげ図も合わせて描画

以下が出力されます。グループ名を指定し、検定したいデータをコピペ、解析を実行すると、それぞれの検定量の表示と、箱ひげ図が描画されています。

今後の展開・アイデア

次回取り組みたいこと;

・生成AIと付き合う際の情報の管理

■ 統計学の参考書

*今回のコードは以下です。

import tkinter as tk
from tkinter import messagebox
from tkinter import scrolledtext
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

plt.rcParams['font.family'] = 'Meiryo'  # 日本語フォント

# データ解析関数
def parse_input(text):
    try:
        text = text.replace('\n', ',')
        return [float(x.strip()) for x in text.split(',') if x.strip() != ''][:30]
    except ValueError:
        return []

def analyze():
    group1 = parse_input(text1.get("1.0", tk.END))
    group2 = parse_input(text2.get("1.0", tk.END))
    label1 = group1_name.get().strip() or "Group1"
    label2 = group2_name.get().strip() or "Group2"

    if len(group1) < 2 or len(group2) < 2:
        messagebox.showwarning("入力エラー", "各グループに最低2つの数値が必要です。")
        return

    result_text = ""
    # 正規性検定
    sw1 = stats.shapiro(group1)
    sw2 = stats.shapiro(group2)
    result_text += f"正規性検定 (Shapiro-Wilk):\n"
    result_text += f"  {label1} のp値: {sw1.pvalue:.4f} ({'正規分布' if sw1.pvalue > 0.05 else '非正規'})\n"
    result_text += f"  {label2} のp値: {sw2.pvalue:.4f} ({'正規分布' if sw2.pvalue > 0.05 else '非正規'})\n"

    # F検定
    f_stat = np.var(group1, ddof=1) / np.var(group2, ddof=1)
    dfn = len(group1) - 1
    dfd = len(group2) - 1
    p_f = 2 * min(stats.f.cdf(f_stat, dfn, dfd), 1 - stats.f.cdf(f_stat, dfn, dfd))
    result_text += f"\nF検定:\n  F値: {f_stat:.4f}, p値: {p_f:.4f}\n"

    # t検定
    equal_var = p_f > 0.05
    t_res = stats.ttest_ind(group1, group2, equal_var=equal_var)
    result_text += f"\nt検定 ({'等分散仮定' if equal_var else '等分散仮定なし'}):\n  p値: {t_res.pvalue:.4f}\n"

    result_box.delete("1.0", tk.END)
    result_box.insert(tk.END, result_text)

    # 箱ひげ図描画
    ax.clear()
    bp = ax.boxplot([group1, group2], labels=[label1, label2], patch_artist=True)
    means = [np.mean(group1), np.mean(group2)]
    ax.plot([1, 2], means, 'r+', markersize=12, label='平均')
    ax.set_title("箱ひげ図", fontsize=12)
    ax.legend()
    canvas.draw()

# GUI作成
root = tk.Tk()
root.title("2群比較ツール(tkinter版)")

frame = tk.Frame(root)
frame.pack(padx=10, pady=10)

# 名前入力
tk.Label(frame, text="グループ1名").grid(row=0, column=0)
group1_name = tk.Entry(frame, width=20)
group1_name.insert(0, "Group1")
group1_name.grid(row=0, column=1)

tk.Label(frame, text="グループ2名").grid(row=0, column=2)
group2_name = tk.Entry(frame, width=20)
group2_name.insert(0, "Group2")
group2_name.grid(row=0, column=3)

# データ入力欄
label1 = tk.Label(frame, text="グループ1データ")
label1.grid(row=1, column=0, columnspan=2)
text1 = scrolledtext.ScrolledText(frame, width=30, height=5)
text1.grid(row=2, column=0, columnspan=2, padx=5)

label2 = tk.Label(frame, text="グループ2データ")
label2.grid(row=1, column=2, columnspan=2)
text2 = scrolledtext.ScrolledText(frame, width=30, height=5)
text2.grid(row=2, column=2, columnspan=2, padx=5)

analyze_btn = tk.Button(frame, text="解析実行", command=analyze)
analyze_btn.grid(row=3, column=0, columnspan=4, pady=10)

result_box = scrolledtext.ScrolledText(root, width=70, height=10)
result_box.pack(padx=10, pady=5)

fig, ax = plt.subplots(figsize=(5, 4))
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack()

root.mainloop()


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