[PYTHON] Je viens de créer un outil pour afficher facilement les données sous forme de graphique par opération GUI

Lorsque je travaille sur l'analyse des données, je pense qu'en plus du suivi numérique des données, il arrive souvent que les caractéristiques des données soient confirmées visuellement à l'aide de graphiques et autres. Il existe de nombreuses tâches de ce type, et j'ai créé un outil appelé "Glance" qui peut afficher des graphiques immédiatement tout en changeant librement la combinaison de données. J'ai utilisé la bibliothèque tkinter de Python pour créer l'interface graphique.

Le fichier peut être trouvé à ici. ** * Je l'ai fait pour une utilisation dans un environnement Windows, il doit donc probablement être modifié séparément dans un environnement Mac ... **

Aperçu

C'est un outil simple qui sélectionne simplement les données lues et les affiche sous forme de graphique. Trois opérations majeures ont été mises en œuvre.

  1. Lisez les données de la sélection de fichiers et affichez la colonne dans une liste sample1.gif

  2. Sélectionnez les données et affichez le graphique

  1. Modifiez dynamiquement la plage d'affichage du graphique avec le curseur sample4.gif

Une brève introduction de la partie accro

À propos de la transmission de valeurs dans tkinter

J'ai utilisé tkinter pour la première fois cette fois, mais l'une des choses qui est restée bloquée est "** Je ne sais pas comment recevoir la valeur de retour de la fonction affectée au widget **". Pour cela, il a semblé nécessaire de définir une classe pour contenir les données et de les transmettre en donnant à chaque objet des données.

Par exemple, dans le cas de cet outil, il existe une fonction appelée fileselect qui lit le fichier, mais la trame de données lue n'est pas retournée par retour, mais est donnée à l'objet dans le processus.

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) #J'ai les données ici.
        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, 'Sélectionnez un fichier csv ou pickle.')

Comment mettre à jour dynamiquement le graphique

Lors de l'utilisation du widget tkinter avec une fonction Vous définirez la fonction d'opération à l'intérieur de la fonction sur la portée de la variable.

Cette fois, nous définissons également new_window pour ouvrir le graphique dans une fenêtre séparée, donc La structure de la fonction «redessiner» qui met à jour le graphique est la suivante.

def main():
    #En traitement
    def new_window():
        def redraw():
            #En traitement
        scale = tk.Scale(command=redraw) #Barre coulissante

Cela entraînera l'exécution de la fonction de rafraîchissement à chaque fois que vous manipulerez l'échelle.

L'intérieur de la fonction de redraw est gratuit, mais après avoir changé le contenu exprimé par matplotlib Veuillez noter que si canvas.draw () n'est pas à la fin, il ne sera pas reflété sur l'interface graphique.

Je ne peux pas séparer le code

C'est un problème non résolu, mais dans mon style d'écriture, c'est dans main () Je ne pouvais pas sortir en tant que fonction ou fichier séparé parce que j'ai défini toutes les autres fonctions. (Mais je ne sais comment faire fonctionner le widget qu'avec une fonction ...)

En conséquence, main () devient long et difficile à lire.

Code entier

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', 'Veuillez sélectionner les données à lire en premier')

    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, 'Sélectionnez un fichier csv ou pickle.')

    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()

Page de référence

Comment afficher le graphique et le modifier dynamiquement À propos du placement des widgets tkinter

Recommended Posts

Je viens de créer un outil pour afficher facilement les données sous forme de graphique par opération GUI
J'ai fait un script pour afficher des pictogrammes
J'ai créé un outil pour compiler nativement Hy
J'ai créé un outil pour obtenir de nouveaux articles
J'ai créé un outil de génération de données texte répétitif "rpttxt"
J'ai créé un outil pour créer un nuage de mots à partir de wikipedia
[Titan Craft] J'ai créé un outil pour invoquer un géant sur Minecraft
Procédure de la construction de l'environnement au test de fonctionnement de testinfra, un outil de test d'environnement de serveur réalisé par Python
J'ai créé une bibliothèque qui lit facilement les fichiers de configuration avec Python
Impressions de toucher Dash, un outil de visualisation de données réalisé par python
J'ai fait une commande pour afficher un calendrier coloré dans le terminal
J'ai créé un outil CLI pour convertir les images de chaque répertoire en PDF
J'ai créé un programme pour vous avertir par LINE lorsque les commutateurs arrivent
J'ai créé un programme pour saisir ce que j'ai mangé et afficher les calories et les sucres
J'ai créé un outil pour convertir Jupyter py en ipynb avec VS Code
J'ai créé un outil d'estampage automatique du navigateur.
J'ai essayé d'afficher la valeur d'altitude du DTM dans un graphique
J'ai fait un outil pour estimer le temps d'exécution de cron (+ débuts de PyPI)
J'ai créé un outil pour corriger les données GPS avec l'API Map Matching de Mapbox (Mapbox Map Matching API)
J'ai créé un outil pour informer Slack des événements Connpass et en ai fait Terraform
J'ai essayé d'expliquer à quoi sert le générateur Python aussi facilement que possible.
J'ai fait un module en langage C qui filtre les images chargées par Python
J'ai créé un outil pour générer du Markdown à partir du fichier JSON Scrapbox exporté
Lien vers les points de données du graphe créé par jupyterlab & matplotlib
J'ai créé un outil pour sauvegarder automatiquement les métadonnées de l'organisation Salesforce
Je souhaite créer facilement un modèle de bruit
J'ai créé un outil utile pour Digital Ocean
J'ai créé une application graphique avec Python + PyQt5
Quoi qu'il en soit, je veux vérifier facilement les données JSON
Addictif quand Kintone est un magasin de données
J'ai créé un outil de collecte de configuration de routeur Config Collecor
Je veux trouver facilement une délicieuse boutique
J'ai fait un graphique de nombres aléatoires avec Numpy
Un graphique sympa pour l'analyse des données de Wiire!
J'ai créé un système qui vous permet de tweeter simplement en passant un appel téléphonique
J'ai oublié d'utiliser VIM, j'ai donc fait une vidéo pour la mémorisation. 3 vidéos par niveau
Je veux facilement implémenter le délai d'expiration en python
Création de l'outil de gestion des utilisateurs Let's Chat
J'ai fait une bibliothèque pour bien séparer les phrases japonaises
J'ai créé un outil de nettoyage pour Google Container Registry
J'ai fait un script pour mettre un extrait dans README.md
Visualisez les données d'itinéraires ferroviaires sous forme de graphique avec Cytoscape 2
J'ai créé un module Python pour traduire les commentaires
J'ai créé un code pour convertir illustration2vec en modèle Keras
Je souhaite créer facilement un environnement de développement basé sur un modèle
Comment afficher DataFrame sous forme de tableau dans Markdown
J'ai fait une commande pour marquer le clip de la table
J'ai créé une bibliothèque python qui fait rouler le rang
Création d'un toolver qui crache le système d'exploitation, Python, les modules et les versions d'outils à Markdown
J'ai créé un outil pour obtenir les liens de réponse d'OpenAI Gym en même temps
J'ai créé une classe pour obtenir le résultat de l'analyse par MeCab dans ndarray avec python
Visualisation des données avec Python - La méthode de dessin simultané de graphes basés sur les attributs avec "Facet" est trop pratique
J'ai créé un outil pour générer automatiquement un simple diagramme ER à partir de l'instruction CREATE TABLE
Création d'un outil qui facilite la définition des paramètres des modèles d'apprentissage automatique
Création d'une méthode pour sélectionner et visualiser automatiquement un graphique approprié pour les pandas DataFrame
〇✕ J'ai fait un jeu
J'ai créé un package pour filtrer les séries chronologiques avec python
J'ai fait une boîte pour me reposer avant que Pepper ne se fatigue
unixtime ← → J'ai essayé de créer une classe qui effectue facilement la conversion datetime
J'ai fait une commande pour générer un commentaire pour une table dans Django
J'ai fait une fonction pour vérifier le modèle de DCGAN