Как визуализировать прогноз matplotlib с помощью графического интерфейса tkinter? - PullRequest
1 голос
/ 21 апреля 2019

У меня есть сценарий, в котором я сделал прогноз для определенного набора данных.Теперь я хочу визуализировать этот прогнозируемый график с помощью Tkinter.

Моя модель машинного обучения выглядит следующим образом, которая состоит из графика:

# Importing Libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import sys

# Importing the Batsmen Dataset
dataset = pd.read_csv('Batsmen/Batsmen.csv')
X = dataset.iloc[:, [1, 2, 3, 4, 5, 6]].values

# Using Elbow Method to find the optimal number of Clusters
from sklearn.cluster import KMeans
wcss = []
for i in range(1, 11):
    kmeans = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0)
    kmeans.fit(X)
    wcss.append(kmeans.inertia_)
plt.plot(range(1, 11), wcss)
plt.title('The Elbow Method')
plt.xlabel('Number of Clusters')
plt.ylabel('WCSS')
plt.show()

Я попробовал, как показано ниже:

from tkinter import *

# these four imports are important
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

def plot():
    # Importing Libraries
    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    import sys

    # Importing the Batsmen Dataset
    dataset = pd.read_csv('Batsmen/Batsmen.csv')
    X = dataset.iloc[:, [1, 2, 3, 4, 5, 6]].values

    # Using Elbow Method to find the optimal number of Clusters
    from sklearn.cluster import KMeans
    wcss = []
    for i in range(1, 11):
        kmeans = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0)
        kmeans.fit(X)
        wcss.append(kmeans.inertia_)

root = Tk()

def app():
    # initialise a window.
    root = Tk()
    root.config(background='white')
    root.geometry("1000x700")

    lab = Label(root, text="Live Plotting", bg = 'white').pack()

    fig = Figure()

    ax = fig.add_subplot(111)
    ax.set_title('The Elbow Method')
    ax.set_xlabel('Number of Clusters')
    ax.set_ylabel('WCSS')
    ax.grid()

    graph = FigureCanvasTkAgg(fig, master=root)
    graph.get_tk_widget().pack(side="top",fill='both',expand=True)

def plotter():
    ax.cla()
    ax.grid()
    dpts = plot()
    ax.plot(range(1, 11), wcss, marker='o', color='orange')
    graph.draw()
    time.sleep(1)

def gui_handler():
    threading.Thread(target=plotter).start()

b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
b.pack()

root.mainloop()

if __name__ == '__main__':
    app()

Но это не работает!

Я просто хочу показать прогноз в графическом интерфейсе Tkinter, и когда я нажимаю кнопку прогнозирования в графическом интерфейсе, я хочу, чтобы график отображался внутри холста графического интерфейса.Итак, может кто-нибудь, пожалуйста, помогите мне сделать то же самое.

1 Ответ

1 голос
/ 21 апреля 2019

Ваш код работает для меня, если я использую root.after() вместо многопоточности.

Возможно, в большинстве сред GUI поток должен (или не может) изменить элемент в графическом интерфейсе.

На моемкомпьютерный код с завершением потоков работает, когда я нажимаю кнопку запуска потока.

Я запускаю plotter, который не использует while и sleep, но after(1000, plotter), чтобы запустить его снова через 1000 мс (1 с)

from tkinter import *
from random import randint

# these two imports are important
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

continuePlotting = False

def change_state():
    global continuePlotting
    if continuePlotting == True:
        continuePlotting = False
    else:
        continuePlotting = True


def data_points():
    f = open("data.txt", "w")
    for i in range(10):
        f.write(str(randint(0, 10))+'\n')
    f.close()

    f = open("data.txt", "r")
    data = f.readlines()
    f.close()

    l = []
    for i in range(len(data)):
        l.append(int(data[i].rstrip("\n")))
    return l

def app():
    # initialise a window.
    root = Tk()
    root.config(background='white')
    root.geometry("1000x700")

    lab = Label(root, text="Live Plotting", bg = 'white').pack()

    fig = Figure()

    ax = fig.add_subplot(111)
    ax.set_xlabel("X axis")
    ax.set_ylabel("Y axis")
    ax.grid()

    graph = FigureCanvasTkAgg(fig, master=root)
    graph.get_tk_widget().pack(side="top",fill='both',expand=True)

    def plotter():
        if continuePlotting:
            ax.cla()
            ax.grid()
            dpts = data_points()
            ax.plot(range(10), dpts, marker='o', color='orange')
            graph.draw()
            root.after(1000, plotter)

    def gui_handler():
        change_state()
        plotter()

    b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
    b.pack()

    root.mainloop()

if __name__ == '__main__':
    app()

РЕДАКТИРОВАТЬ: в новом коде вы не запускаете цикл, поэтому вам не нужны потоки или after()

Но у вас естьдругие основные проблемы:

У вас неправильный абзац и mainloop() находится за пределами app() - выполняется до app()

В предыдущей версии plotter был внутри app() - еслион вам нужен снаружи, тогда у вас есть проблемы с локальными переменными - такими как ax - и вы должны использовать global, чтобы иметь доступ к этим переменным в другой функции.Или вы должны запустить функцию с этими значениями в качестве аргументов - т.е.plotter(ax, wcss, graph)

Эта версия использует global, и она работает для меня.У меня нет вашего CSV, и я не хочу запускать sklearn, поэтому я поместил некоторые поддельные данные.

from tkinter import *

# these four imports are important
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

def plot():
    # Importing Libraries
    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    import sys

    # Importing the Batsmen Dataset
#    dataset = pd.read_csv('Batsmen/Batsmen.csv')
    dataset = pd.DataFrame({
        'a': range(10),
        'b': range(10),
        'c': range(10),
        'd': range(10),
        'e': range(10),
        'f': range(10),
        'g': range(10),
    })

    X = dataset.iloc[:, [1, 2, 3, 4, 5, 6]].values

    # Using Elbow Method to find the optimal number of Clusters
    from sklearn.cluster import KMeans

    global wcss
    wcss = range(1, 11)
    #wcss = []
#    for i in range(1, 11):
#        kmeans = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0)
#        kmeans.fit(X)
#        wcss.append(kmeans.inertia_)

def plotter():
    global wcss
    global ax
    global graph

    ax.cla()
    ax.grid()
    dpts = plot()
    ax.plot(range(1, 11), wcss, marker='o', color='orange')
    graph.draw()

def gui_handler():
    plotter()

def app():
    global ax
    global graph

    # initialise a window.
    root = Tk()
    root.config(background='white')
    root.geometry("1000x700")

    lab = Label(root, text="Live Plotting", bg = 'white').pack()

    fig = Figure()

    ax = fig.add_subplot(111)
    ax.set_title('The Elbow Method')
    ax.set_xlabel('Number of Clusters')
    ax.set_ylabel('WCSS')
    ax.grid()

    graph = FigureCanvasTkAgg(fig, master=root)
    graph.get_tk_widget().pack(side="top",fill='both',expand=True)

    b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
    b.pack()

    root.mainloop()

if __name__ == '__main__':
    app()
...