基于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()
使用说明
- 运行代码后首先选择要分析的CSV文件,根据弹窗提示选择文件是否包含表头、是否删除空值
- 进入主界面后,修改左侧的参数值,右侧的统计汇总表和直方图会自动刷新
- 点击「查看原始数据集」按钮可查看导入的原始数据
- 调整完成后点击退出按钮或关闭窗口即可退出
内容的提问来源于stack exchange,提问作者data_curious
相关产品推荐
相关产品推荐

