見出し画像

#19 Pythonで始めるヒストグラムver1.1、チャレンジ AI×100業務(製造業)

チャレンジ#15では、ヒストグラムを描画しました。折角のヒストグラムですから、今回は種々の統計量を加えたものにします。


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


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

  • ChatGPT 4o

  • Visual Studio Code環境下でのPython

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

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

ChatGPT 4oにて以下のプロンプト
*前回のコードを参照しつつの会話です。

ヒストグラムの下に横向きの箱ひげ図を配置してください。
データは、グラフの右に移動して、以下の統計量や検定結果を表示してください 。
正規性検定(p値)、平均値、標準偏差、分散、歪度、尖度、データ数、最小値・・(略)

コードを実行すると、以下が描画されました。

統計量が加わるとヒストグラムも引き締まった感じがします。
*p値からデータは正規性を有しているようですね。
*95%信頼区間は平均に対してのものです。

やることが決まっている際は、このようなアプリは便利ですね。

今後の展開・アイデア

次回取り組みたいこと;

・先日、弊社のホームページ製作業者と打ち合わせた際の話です。

■ 今日のコード

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

# 日本語フォントの設定(文字化け対策)
# rcParams['font.family'] = 'IPAexGothic'  # または 'MS Gothic', 'Yu Gothic', 'Noto Sans CJK JP' など

class HistogramApp:
    def __init__(self, root):
        self.root = root
        self.root.title("ヒストグラム描画アプリ")

        self.label = tk.Label(root, text="数値データを入力(最大30個、Excelからのコピペも可):")
        self.label.pack()

        self.entry = tk.Text(root, height=5, width=50)
        self.entry.pack()

        self.button = tk.Button(root, text="描画", command=self.draw_histogram)
        self.button.pack()

        self.result_frame = tk.Frame(root)
        self.result_frame.pack(side=tk.RIGHT, padx=10)

        self.result_text = tk.Text(self.result_frame, height=30, width=50)
        self.result_text.pack()

        self.canvas_frame = tk.Frame(root)
        self.canvas_frame.pack(side=tk.LEFT)

    def draw_histogram(self):
        input_data = self.entry.get("1.0", tk.END).strip()
        try:
            # カンマ、スペース、改行、タブで区切る(Excelコピペ対応)
            data_str_list = re.split(r'[\s,]+', input_data)
            data = [float(x.strip()) for x in data_str_list if x.strip() != ""]

            n = len(data)
            if n > 30:
                messagebox.showerror("エラー", "データは最大30個までです。")
                return

            # 基本統計量
            mean = np.mean(data)
            std_dev = np.std(data, ddof=1)
            variance = np.var(data, ddof=1)
            skewness = stats.skew(data)
            kurtosis = stats.kurtosis(data)
            _, p_value = stats.shapiro(data)

            # 箱ひげ図用の統計量
            minimum = np.min(data)
            q1 = np.percentile(data, 25)
            median = np.median(data)
            q3 = np.percentile(data, 75)
            maximum = np.max(data)

            # 平均の95%信頼区間
            ci_low, ci_high = stats.t.interval(0.95, df=n-1, loc=mean, scale=std_dev/np.sqrt(n))

            # 統計結果を表示
            self.result_text.delete("1.0", tk.END)
            self.result_text.insert(tk.END, f"▶ 統計量・検定結果\n")
            self.result_text.insert(tk.END, f"--------------------------\n")
            self.result_text.insert(tk.END, f"データ数     : {n}\n\n")
            self.result_text.insert(tk.END, f"正規性検定(p値) : {p_value:.4f}\n\n")
            self.result_text.insert(tk.END, f"平均値      : {mean:.2f}\n")
            self.result_text.insert(tk.END, f"標準偏差     : {std_dev:.2f}\n")
            self.result_text.insert(tk.END, f"分散       : {variance:.2f}\n")
            self.result_text.insert(tk.END, f"歪度       : {skewness:.2f}\n")
            self.result_text.insert(tk.END, f"尖度       : {kurtosis:.2f}\n\n")
            self.result_text.insert(tk.END, f"最小値      : {minimum:.2f}\n")
            self.result_text.insert(tk.END, f"第1四分位数   : {q1:.2f}\n")
            self.result_text.insert(tk.END, f"中央値      : {median:.2f}\n")
            self.result_text.insert(tk.END, f"第3四分位数   : {q3:.2f}\n")
            self.result_text.insert(tk.END, f"最大値      : {maximum:.2f}\n\n")
            self.result_text.insert(tk.END, f"95%信頼区間   : [{ci_low:.2f}, {ci_high:.2f}]\n")

            # グラフの描画(ヒストグラムと箱ひげ図)
            fig = plt.figure(figsize=(8, 6))
            gs = fig.add_gridspec(2, 1, height_ratios=[4, 1])

            ax1 = fig.add_subplot(gs[0])  # ヒストグラム
            ax1.hist(data, bins='auto', edgecolor='black')
            ax1.axvline(mean, color='red', linestyle='dashed', linewidth=1.5, label=f"平均値: {mean:.2f}")
            ax1.set_title("ヒストグラム")
            ax1.set_ylabel("度数")
            ax1.legend()

            ax2 = fig.add_subplot(gs[1])  # 横向きの箱ひげ図
            ax2.boxplot(
                data,
                vert=False,
                patch_artist=True,
                flierprops=dict(marker='+', color='red', markersize=8)
            )
            ax2.set_xlabel("値")
            ax2.set_yticks([])

            for widget in self.canvas_frame.winfo_children():
                widget.destroy()

            canvas = FigureCanvasTkAgg(fig, master=self.canvas_frame)
            canvas.draw()
            canvas.get_tk_widget().pack()

        except ValueError:
            messagebox.showerror("エラー", "数値を正しく入力してください(例: 10 20 30 または Excel からのコピペ)。")

if __name__ == "__main__":
    root = tk.Tk()
    app = HistogramApp(root)
    root.mainloop()


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