Bei der Arbeit an der Datenanalyse denke ich, dass neben der numerischen Verfolgung der Daten häufig die Eigenschaften der Daten mithilfe von Diagrammen oder dergleichen visuell bestätigt werden.
Es gibt viele solcher Aufgaben, und ich habe ein Tool namens "Glance" erstellt, mit dem Diagramme sofort angezeigt werden können, während die Datenkombination frei geändert werden kann.
Ich habe Pythons tkinter
Bibliothek verwendet, um die GUI zu erstellen.
Die Datei finden Sie unter hier. ** * Da es für die Verwendung in einer Windows-Umgebung erstellt wurde, muss es in einer Mac-Umgebung wahrscheinlich separat geändert werden ... **
Es ist ein einfaches Werkzeug, das einfach aus den gelesenen Daten auswählt und diese als Grafik anzeigt. Es wurden drei Hauptoperationen implementiert.
Lesen Sie die Daten aus der Dateiauswahl und zeigen Sie die Spalte in einer Liste an
Wählen Sie Daten aus und zeigen Sie das Diagramm an
Ich habe tkinter dieses Mal zum ersten Mal verwendet, aber eines der Dinge, die hängen geblieben sind, ist "** Ich weiß nicht, wie ich den Rückgabewert der dem Widget zugewiesenen Funktion erhalten soll **". Zu diesem Zweck schien es notwendig zu sein, eine Klasse zu definieren, die Daten enthält, und diese zu übergeben, indem jedem Objekt Daten gegeben werden.
Im Fall dieses Tools gibt es beispielsweise eine Funktion namens "fileselect", die aus der Datei liest, aber der gelesene Datenrahmen wird nicht zurückgegeben, sondern an das Objekt im Prozess übergeben.
def fileselect():
root = tkinter.Tk()
root.withdraw()
fTyp = [("", "*")]
iDir = os.path.abspath(os.path.dirname(__file__))
model.path = tkinter.filedialog.askopenfilename(filetypes=fTyp,
initialdir=iDir)
suffix = model.path.rsplit('.', 1)[1]
if suffix == 'csv' or suffix == 'pkl':
model.set_data(suffix) #Ich habe die Daten hier.
graph.config(state='active')
Entry1.insert(tk.END, model.path)
line_size = columns_list.size()
columns_list.delete(0, line_size)
for column in enumerate(model.data.columns):
columns_list.insert(tk.END, column)
else:
tkinter.messagebox.showinfo(model.path, 'Wählen Sie eine CSV- oder Pickle-Datei aus.')
Beim Betrieb des tkinter-Widgets mit einer Funktion Sie definieren die Operationsfunktion innerhalb der Funktion im Bereich der Variablen.
Dieses Mal definieren wir auch "new_window", um das Diagramm in einem separaten Fenster zu öffnen Die Struktur der "Neuzeichnen" -Funktion, die das Diagramm aktualisiert, ist wie folgt.
def main():
#wird bearbeitet
def new_window():
def redraw():
#wird bearbeitet
scale = tk.Scale(command=redraw) #Schiebeleiste
Dadurch wird die Neuzeichnungsfunktion jedes Mal ausgeführt, wenn Sie die Skala bearbeiten.
Das Innere der Redraw-Funktion ist frei, jedoch nach Änderung des von matplotlib ausgedrückten Inhalts Bitte beachten Sie, dass wenn "canvas.draw ()" nicht am Ende steht, dies nicht in der GUI angezeigt wird.
Dies ist ein ungelöstes Problem, aber in meinem Schreibstil ist es in main () Ich konnte nicht als Funktion oder separate Datei ausgehen, da ich alle anderen Funktionen definiert habe. (Aber ich weiß nur, wie man das Widget mit einer Funktion bedient ...)
Infolgedessen wird main () lang und schwer zu lesen. Was ist falsch?
import os
import tkinter as tk
import tkinter.filedialog
import tkinter.messagebox
import japanize_matplotlib
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import numpy as np
import pandas as pd
def main():
class model_data:
def __init__(self):
self.data = pd.DataFrame()
self.path = ''
self.columns = []
def set_path(self, file_path):
self.path = file_path
def set_data(self, suffix):
if suffix == 'csv':
self.data = pd.read_csv(self.path)
elif suffix == 'pkl':
self.data = pd.read_pickle(self.path)
def new_window(event):
if any(model.data):
def _quit_sub():
sub_win.destroy()
def _redraw(event):
min_lim = min_scale.get()
max_lim = max_scale.get()
val = []
if min_lim >= max_lim:
return
else:
t = target.iloc[min_lim:max_lim, :]
for index in selection:
label = target.columns[index]
val.append(t[label].max())
val.append(t[label].min())
max_val = max(val)
min_val = min(val)
ax.set_xlim(min_lim, max_lim)
ax.set_ylim(min_val, max_val)
canvas.draw()
selection = columns_list.curselection()
sub_win = tk.Toplevel(root)
sub_win.configure(bg='white')
sub_win.wm_title("Embedding in Tk")
target = model.data.copy()
target.reset_index(drop=True, inplace=True)
fig = Figure(figsize=(10, 4), dpi=100)
ax = fig.add_subplot(111)
if norm_bln.get():
for index in selection:
label = target.columns[index]
max_num = target[label].max()
min_num = target[label].min()
target[label] = (target[label] - min_num) / (max_num - min_num)
ax.plot(target.index,
target[label],
label=label)
else:
for index in selection:
label = target.columns[index]
ax.plot(target.index,
target[label],
label=label)
canvas_frame = tk.Frame(master=sub_win, bg='white')
canvas_frame.pack(side=tk.LEFT)
canvas = FigureCanvasTkAgg(fig,
master=canvas_frame)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP,
fill=tk.BOTH,
expand=1)
control_frame = tk.Frame(master=sub_win)
control_frame.pack(side=tk.RIGHT)
toolbar = NavigationToolbar2Tk(canvas,
canvas_frame)
toolbar.update()
canvas.get_tk_widget().pack(side=tk.TOP,
fill=tk.BOTH,
expand=True)
min_scale = tk.Scale(control_frame,
label='Min',
orient='h',
from_=0,
bg='light blue',
resolution=1,
to=model.data.shape[0]-1,
command=_redraw)
min_scale.pack(anchor=tk.NW)
max_scale = tk.Scale(control_frame,
label='Max',
orient='h',
from_=1,
bg='tan1',
resolution=1,
to=model.data.shape[0],
command=_redraw)
max_scale.set(target.shape[0])
max_scale.pack(anchor=tk.NW)
button = tkinter.Button(master=canvas_frame,
text="Quit",
command=_quit_sub)
button.pack(side=tkinter.BOTTOM)
else:
tkinter.messagebox.showinfo('Glance.py', 'Bitte wählen Sie zuerst die zu lesenden Daten aus')
def fileselect():
root = tkinter.Tk()
root.withdraw()
fTyp = [("", "*")]
iDir = os.path.abspath(os.path.dirname(__file__))
model.path = tkinter.filedialog.askopenfilename(filetypes=fTyp,
initialdir=iDir)
suffix = model.path.rsplit('.', 1)[1]
if suffix == 'csv' or suffix == 'pkl':
model.set_data(suffix)
graph.config(state='active')
Entry1.insert(tk.END, model.path)
line_size = columns_list.size()
columns_list.delete(0, line_size)
for column in enumerate(model.data.columns):
columns_list.insert(tk.END, column)
else:
tkinter.messagebox.showinfo(model.path, 'Wählen Sie eine CSV- oder Pickle-Datei aus.')
def _quit(event):
root.quit()
root.destroy()
root = tk.Tk()
model = model_data()
root.title('Glance')
root.geometry('680x300')
frame1 = tk.Frame(bd=3, relief=tk.SUNKEN, pady=5)
frame1.pack(padx=5, pady=5, ipadx=10, ipady=10, side=tk.LEFT)
Static1 = tk.Label(frame1, text='File Path')
Static1.pack()
Entry1 = tk.Entry(frame1, width=80)
Entry1.insert(tk.END, model.path)
Entry1.pack()
Static1 = tk.Label(frame1, text='Column Names')
Static1.pack()
var = tk.StringVar(value=[])
columns_list = tk.Listbox(frame1,
listvariable=var,
width=80,
selectmode='multiple')
scrollbar = tk.Scrollbar(frame1,
command=columns_list.yview)
columns_list.yscrollcommand = scrollbar.set
scrollbar.pack(fill=tk.BOTH,
side=tk.RIGHT)
columns_list.pack()
Button1 = tk.Button(frame1,
text='SelectFile',
width=10,
command=fileselect)
Button1.pack(pady=5)
frame2 = tk.Frame()
frame2.pack(padx=5, pady=5, ipadx=10, ipady=10, fill=tk.BOTH)
norm_bln = tk.BooleanVar()
norm_bln.set('False')
norm = tkinter.Checkbutton(frame2,
variable=norm_bln,
text='Norm')
norm.pack()
graph = tk.Button(frame2,
text='Graph',
width=10,
state='disable')
graph.bind("<Button-1>", new_window)
graph.pack()
frame3 = tk.Frame()
frame3.pack(padx=5, pady=5, ipadx=10, ipady=10, side=tk.BOTTOM)
Button2 = tk.Button(frame3, text='Exit', width=5)
Button2.bind("<Button-1>", _quit)
Button2.pack()
root.mainloop()
if __name__ == "__main__":
main()
So zeigen Sie das Diagramm an und ändern es dynamisch Informationen zur Platzierung des tkinter-Widgets
Recommended Posts