matplotlib散点图选择器

时间:2016-01-11 17:15:44

标签: python matplotlib

我想要plot_date上的选择器,但它没有响应点击次数。甚至其他事件也不会连接到图表。

此课程将从本地数据库获取推文以进行情感分析。

current screenshot programma

import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.dates as md
from matplotlib.dates import DayLocator, HourLocator, DateFormatter, drange
import matplotlib.pyplot as plt
import tkinter as Tk
from Core.Database import Database
from numpy import arange

matplotlib.use('TkAgg')
plt.style.use('ggplot')

class SentimentGraph:
    figure = None
    axes = None

    timeStamps = []
    sentiment_score = []

    def __init__(self, create_figure=True):
        # get data from database.
        self.get_data()

        # create figure.
        if create_figure:
            self.figure = plt.figure()

        # draw graph in figure
        self.draw_graph(self.figure)

    def draw_graph(self, figure):

        neutral = 0
        negative = 0
        positive = 0

        for score in self.sentiment_score:
            if score == 0:
                neutral += 1
            elif score > 0:
                positive += 1
            elif score < 0:
                negative += 1

        self.figure, axes = plt.subplots(ncols=2, nrows=1)
        ax1, ax2 = axes.ravel()

        # The slices will be ordered and plotted counter-clockwise.
        labels = 'neutral', 'Negative', 'Positive'
        sizes = [neutral, positive, negative]
        colors = ['yellowgreen', 'lightcoral', 'lightskyblue']
        explode = (0, 0.1, 0.1)  # only "explode" the 2nd slice (i.e. 'Hogs')

        ax1.pie(sizes, explode=explode, labels=labels, colors=colors,
                autopct='%1.1f%%', shadow=True, startangle=90,
                radius=0.25, center=(0, 0), frame=True)

        # Set aspect ratio to be equal so that pie is drawn as a circle.
        ax1.axis('equal')
        ax1.axis('off')

        ax2.plot_date(self.timeStamps, self.sentiment_score, alpha=0.5, picker=True)

        def onclick(event):
            index = event.ind
            xy = event.artist.get_offsets()
            print('--------------')
            print(xy[index])

        self.figure.canvas.mpl_connect('pick_event', onclick)

        ax2.set_title("Sentiment score")
        ax2.set_ylabel("Sentiment score")
        xfmt = md.DateFormatter('%Y-%m-%d %H:%M')

        ax2.xaxis.set_minor_locator(HourLocator(arange(0, 25, 6)))
        ax2.xaxis.set_major_formatter(DateFormatter('%H:%M'))
        ax2.xaxis.set_major_formatter(xfmt)

        ax2.fmt_xdata = md.DateFormatter('%Y-%m-%d %H:%M')
        self.figure.autofmt_xdate()

    def get_data(self):
        db = Database()
        result = db.query(
            ''' select sentiment_score, posted_at / 1000 as timestamp from tweets ''')
        rows = result.fetchall()

        for row in rows:
            self.sentiment_score.append(row[0])
            # convert unix timestamp to matplotlib compatible
            date = matplotlib.dates.epoch2num(row[1])
            self.timeStamps.append(date)
        return True


if __name__ == "__main__":
    # change config db file location
    import config

    config.DB_FILE = "../tweets.db"

    # create window
    root = Tk.Tk()
    root.wm_title("time line")

    graph = SentimentGraph()


    def _quit():
        root.quit()  # stops mainloop
        root.destroy()  # this is necessary on Windows to prevent
        # Fatal Python Error: PyEval_RestoreThread: NULL tstate


    # a tk.DrawingArea
    canvas = FigureCanvasTkAgg(graph.figure, master=root)
    canvas.show()
    canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

    toolbar = NavigationToolbar2TkAgg(canvas, root)
    toolbar.update()
    canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

    button = Tk.Button(master=root, text='Quit', command=_quit)
    button.pack(side=Tk.BOTTOM)

    Tk.mainloop()
    # If you put root.destroy() here, it will cause an error if
    # the window is closed with the window manager.

1 个答案:

答案 0 :(得分:2)

问题的根源在于您没有在Tkinter应用程序中嵌入您的数字。

相反,当您致电plt.figureplt.subplots时,您需要创建一个全新的tkinter小部件和窗口。然后,你捎带&#34;另一个画布位于该预先存在的图形之上并在您的应用程序中使用它。

因为matplotlib认为该图是属于您使用plt.subplots创建的原始图形,所以它没有注册任何鼠标事件。

当您在另一个应用程序中嵌入图形时,必须使用手动创建的图形。您无法真正致电plt.figureplt.subplots(或plt.anything

要解决您的问题,请使用手动创建的Figure对象在应用程序内设置画布,类似于文档中的嵌入示例。