【发布时间】:2021-12-13 19:48:19
【问题描述】:
我在 Python 中遇到了问题。请看下面的代码。它在控制台中生成汇总统计信息和直方图。但是,我想使用 PySimpleGUI 创建一个 GUI,它将提供一个 GUI,允许用户更改绘图的参数,因此每次都会生成新的直方图和汇总统计信息。我对如何进行此操作一无所知,因为我对 Python 和 Stack Overflow 还是很陌生。我希望在运行代码时出现一个用户界面,要求用户更改用于生成绘制直方图的数据集的方程中的参数。 `
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
def read_table():
sg.set_options(auto_size_buttons=True)
filename = sg.popup_get_file(
'Dataset to read',
title='Dataset to read',
no_window=True,
file_types=(("CSV Files", ".csv"), ("Text Files", "*.txt")))
# --- populate table with file contents --- #
if filename == '':
return
colnames_prompt = sg.popup_yes_no('Does this file have column names already?')
nan_prompt = sg.popup_yes_no('Drop NaN entries?')
if filename is not None:
fn = filename.split('/')[-1]
try:
if colnames_prompt == 'Yes':
df = pd.read_csv(filename, sep=',', engine='python')
# Uses the first row (which should be column names) as columns names
header_list = list(df.columns)
# Drops the first row in the table (otherwise the header names and the first row will be the same)
data = df[1:].values.tolist()
else:
df = pd.read_csv(filename, sep=',', engine='python', header=None)
# Creates columns names for each column ('column0', 'column1', etc)
header_list = ['column' + str(x) for x in range(len(df.iloc[0]))]
df.columns = header_list
# read everything else into a list of rows
data = df.values.tolist()
# NaN drop?
if nan_prompt == 'Yes':
df = df.dropna()
return df, data, header_list, fn
except:
sg.popup_error('Error reading file')
return
def show_table(data, header_list, fn):
layout = [
[sg.Table(values=data,
headings=header_list,
font='Helvetica',
pad=(25, 25),
display_row_numbers=False,
auto_size_columns=True,
num_rows=min(25, len(data)))]
]
window = sg.Window(fn, layout, grab_anywhere=False)
event, values = window.read()
window.close()
def show_stats(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 = ['Summary Statistics'] + header_list
layout = [
[sg.Table(values=data[12:],
headings=header_list,
font='Helvetica',
pad=(12, 12),
display_row_numbers=False,
auto_size_columns=True,
num_rows=min(25, len(data)))]
]
window = sg.Window("Statistics", layout, grab_anywhere=False)
event, values = window.read()
window.close()
def plot_fig(df):
"""
Plots
"""
# Identify link to arrays
input_file = r"input_csv_files/testfile.csv"
# Read input files using pandas dataframe
data_hss = pd.read_csv(input_file, na_values=':', usecols=['result1'])
data_sp = pd.read_csv(input_file, na_values=':', usecols=['result2'])
# Read input files from one file
data = pd.read_csv(input_file, na_values=':', usecols=['result1', 'result2'])
# Prepare files by eliminating NaN values
dataDrop_hss = data_hss.dropna(how='any', subset=['result1'], axis=0)
dataDrop_sp = data_sp.dropna(how='any', subset=['result2'], axis=0)
# Make a separate list for each histogram
hss = list(dataDrop_hss['result1'])
s_p = list(dataDrop_sp['result2'])
# Assign colors to each histogram and the legend names
colors = ['tab:blue', 'tab:orange']
names = ['hss', 'sp']
# Plot the histogram
fig, ax1 = plt.subplots()
ax1.hist([hss, s_p], bins=20, label=names, color=colors)
ax1.set_xlim(-0.14, 0.30)
ax1.set_ylim(0, 120)
plt.gca().xaxis.set_major_formatter(PercentFormatter(1))
# Format the plots
plt.xlabel('Return')
plt.ylabel('Count')
plt.title('hss and sp')
plt.legend(loc='upper right')
# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
# ------------------------------- Beginning of Matplotlib helper code -----------------------
def draw_figure(canvas, figure):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
# ------------------------------- Beginning of GUI CODE -------------------------------
# Define the window layout
layout = [[sg.Text('Plot test')],
[sg.Canvas(key='-CANVAS-')],
[sg.Button('Ok')]]
# create the form and show it without the plot
window = sg.Window('graph', layout, location=(0, 0), finalize=True, element_justification='center',
font='Helvetica 18', resizable=True)
# Add the plot to the window
draw_figure(window['-CANVAS-'].TKCanvas, fig)
event, values = window.read()
window.close()
def main():
df, data, header_list, fn = read_table()
# Show data?
show_prompt = sg.popup_yes_no('Show the dataset?')
if show_prompt == 'Yes':
show_table(data, header_list, fn)
# Show stats?
stats_prompt = sg.popup_yes_no('Show the descriptive stats?')
if stats_prompt == 'Yes':
show_stats(df)
# Show a plot?
plot_prompt = sg.popup_yes_no('Show a histogram plot?')
if plot_prompt == 'Yes':
plot_fig(df)
# Executes main
if __name__ == '__main__':
main()
`
这是我得到的汇总统计输出,但我没有用户界面供用户更改输入变量以操作图表和汇总统计
直方图:
汇总统计:
【问题讨论】:
-
可能首先创建带有一些用于参数的输入/输入/文本字段的 GUI,并使用按钮运行函数,该函数将从小部件中获取参数并进行计算。
-
谢谢。这是我的问题。我可以看到如何创建 GUI,但是如何使按钮能够使用输入参数进行计算?换句话说,如何将用户输入链接到执行计算的函数定义?
-
你不要链接它 - 每个小部件都有自己的
key并且 Button 应该运行从小部件获取值并使用值运行计算的函数。 -
谢谢。例如,当我运行我的代码时,我得到了@Jason Yang 显示的界面。但是如果我点击直方图栏,什么也不会发生。显示统计信息栏产生预期的输出。我需要在那里放什么
key? -
您是否在控制台中运行它以查看错误消息?您是否将函数添加到代码中?如果您没有添加,那么它可能会在控制台而不是预期的窗口中显示错误消息。并查看答案中的代码 - 在
Input(key='Dataset')中有key,后来它使用event, values = window.read()从GUI 获取所有值,并使用values["Dataset"]从Input(key='Dataset')获取值 - 所以它使用相同的Dataset在Input()中有key='Dataset'
标签: python user-interface pysimplegui