You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PySimpleGUI开发参数可调的统计汇总表与直方图生成GUI

PySimpleGUI动态参数调整功能实现方案

核心调整逻辑

  • 将原分散的独立弹窗整合为单主窗口,拆分参数调节、统计结果展示、直方图绘制三个功能区域
  • 为所有参数控件开启enable_events=True属性,参数变更时自动触发更新逻辑
  • 移除绘图函数中硬编码的本地文件读取逻辑,直接使用导入的DataFrame数据源
  • 封装独立的统计刷新、绘图刷新函数,每次参数变更后先清空旧内容再渲染新结果,避免内容堆叠

修改后可运行代码

import PySimpleGUI as sg
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.ticker import PercentFormatter

# 全局变量保存当前画布对象,用于重绘前清除
current_fig_agg = None

def read_table():
    sg.set_options(auto_size_buttons=True)
    filename = sg.popup_get_file(
        '选择数据集',
        title='数据集读取',
        no_window=True,
        file_types=(("CSV Files", ".csv"), ("Text Files", "*.txt")))
    if filename == '':
        return

    colnames_prompt = sg.popup_yes_no('文件是否已包含列名?')
    nan_prompt = sg.popup_yes_no('是否删除空值条目?')

    if filename is not None:
        fn = filename.split('/')[-1]
        try:
            if colnames_prompt == 'Yes':
                df = pd.read_csv(filename, sep=',', engine='python')
                header_list = list(df.columns)
                data = df[1:].values.tolist()
            else:
                df = pd.read_csv(filename, sep=',', engine='python', header=None)
                header_list = ['column' + str(x) for x in range(len(df.iloc[0]))]
                df.columns = header_list
                data = df.values.tolist()
            if nan_prompt == 'Yes':
                df = df.dropna()
            return df, data, header_list, fn
        except:
            sg.popup_error('文件读取错误')
            return

def get_stats_data(df):
    stats = df.describe().T
    header_list = list(stats.columns)
    data = stats.values.tolist()
    for i, d in enumerate(data):
        d.insert(0, list(stats.index)[i])
    header_list = ['统计项'] + header_list
    return data, header_list

def draw_figure(canvas, figure):
    global current_fig_agg
    # 先清除旧画布
    if current_fig_agg:
        current_fig_agg.get_tk_widget().forget()
        plt.close('all')
    # 绘制新画布
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
    current_fig_agg = figure_canvas_agg
    return figure_canvas_agg

def update_plot(df, bins, x_min, x_max, y_max):
    # 直接使用传入的df,不再硬编码读取文件
    dataDrop_hss = df[['result1']].dropna(how='any', subset=['result1'], axis=0)
    dataDrop_sp = df[['result2']].dropna(how='any', subset=['result2'], axis=0)
    hss = list(dataDrop_hss['result1'])
    s_p = list(dataDrop_sp['result2'])
    colors = ['tab:blue', 'tab:orange']
    names = ['hss', 'sp']
    # 绘图
    fig, ax1 = plt.subplots(figsize=(8,4))
    ax1.hist([hss, s_p], bins=bins, label=names, color=colors)
    ax1.set_xlim(x_min, x_max)
    ax1.set_ylim(0, y_max)
    ax1.xaxis.set_major_formatter(PercentFormatter(1))
    plt.xlabel('收益率')
    plt.ylabel('计数')
    plt.title('hss和sp分布直方图')
    plt.legend(loc='upper right')
    plt.tight_layout()
    return fig

def main():
    res = read_table()
    if not res:
        return
    df, data, header_list, fn = res
    # 获取初始统计数据
    stats_data, stats_header = get_stats_data(df)
    # 主窗口布局
    param_col = [
        [sg.Text('参数调节', font='Helvetica 14 bold')],
        [sg.Text('直方图bin数量:'), sg.Input(default_text='20', key='-BINS-', size=(10,1), enable_events=True)],
        [sg.Text('X轴最小值:'), sg.Input(default_text='-0.14', key='-XMIN-', size=(10,1), enable_events=True)],
        [sg.Text('X轴最大值:'), sg.Input(default_text='0.30', key='-XMAX-', size=(10,1), enable_events=True)],
        [sg.Text('Y轴最大值:'), sg.Input(default_text='120', key='-YMAX-', size=(10,1), enable_events=True)],
        [sg.Button('查看原始数据集', key='-SHOW-DATA-')],
        [sg.Button('退出', key='-EXIT-')]
    ]
    right_col = [
        [sg.Text('统计汇总', font='Helvetica 14 bold')],
        [sg.Table(values=stats_data, headings=stats_header, key='-STATS-TABLE-',
                  auto_size_columns=True, num_rows=8, size=(70,8))],
        [sg.Text('直方图', font='Helvetica 14 bold')],
        [sg.Canvas(key='-CANVAS-', size=(70,400))]
    ]
    layout = [
        [sg.Column(param_col, pad=(10,10)), sg.VSeparator(), sg.Column(right_col, pad=(10,10))]
    ]
    window = sg.Window('数据统计分析工具', layout, finalize=True, resizable=True, font='Helvetica 12')
    # 初始绘制直方图
    init_fig = update_plot(df, 20, -0.14, 0.30, 120)
    draw_figure(window['-CANVAS-'].TKCanvas, init_fig)
    # 事件循环
    while True:
        event, values = window.read()
        if event in (sg.WINDOW_CLOSED, '-EXIT-'):
            break
        # 查看原始数据集
        if event == '-SHOW-DATA-':
            show_layout = [
                [sg.Table(values=data, headings=header_list, auto_size_columns=True, num_rows=min(25, len(data)))]
            ]
            show_window = sg.Window(fn, show_layout, modal=True)
            show_window.read(close=True)
        # 参数变更触发更新
        if event in ('-BINS-', '-XMIN-', '-XMAX-', '-YMAX-'):
            try:
                bins = int(values['-BINS-'])
                x_min = float(values['-XMIN-'])
                x_max = float(values['-XMAX-'])
                y_max = int(values['-YMAX-'])
                # 更新统计表格
                new_stats_data, _ = get_stats_data(df)
                window['-STATS-TABLE-'].update(values=new_stats_data)
                # 更新直方图
                new_fig = update_plot(df, bins, x_min, x_max, y_max)
                draw_figure(window['-CANVAS-'].TKCanvas, new_fig)
            except:
                # 参数格式错误时不更新
                pass
    window.close()
    plt.close('all')

if __name__ == '__main__':
    main()

使用说明

  1. 运行代码后首先选择要分析的CSV文件,根据弹窗提示选择文件是否包含表头、是否删除空值
  2. 进入主界面后,修改左侧的参数值,右侧的统计汇总表和直方图会自动刷新
  3. 点击「查看原始数据集」按钮可查看导入的原始数据
  4. 调整完成后点击退出按钮或关闭窗口即可退出

内容的提问来源于stack exchange,提问作者data_curious

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:45:04