【问题标题】:Python PyQT/Seaborn - Interactive charts, keyboard arrow controls and speedPython PyQT/Seaborn - 交互式图表、键盘箭头控件和速度
【发布时间】:2015-10-03 19:46:33
【问题描述】:

我正在使用 seaborn 包创建一个交互式图表。 这是一个简单的图表,x 轴为日期,y 轴为 0 到 5 的值 我可以使用箭头键左右移动光标条,并使用 num 键设置图表的 y 值(并将图表的 y 值及其时间戳导出到 csv)。 但是,当使用较大的日期范围时,程序会变得异常缓慢。 我按箭头键将光标移动一格,但可能需要一到两秒才能做出反应。 (关键控制是用PyQT完成的) 知道我可以做些什么来加快速度吗?

请随意复制粘贴代码并在python中运行以查看程序:

import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
from datetime import timedelta, date
import numpy as np
matplotlib.use('Qt4Agg')
import seaborn as sns
from matplotlib.widgets import Button
import matplotlib.lines
from matplotlib.lines import Line2D
import csv
from itertools import izip



dates = []
values = []

sns.set(style="ticks")

fig = plt.figure(1, figsize=(25,7))
fig.clf()
ax = fig.add_subplot(111)
fig.canvas.draw()
plt.ylim(0,5)

horizontal_position = 0

periods = 365
idx = pd.DatetimeIndex(start='2010-01-01', freq='d', periods=periods)
index_delete = []
for i in range(idx.size):
    if idx[i].dayofweek == 6 or idx[i].dayofweek == 5:
        index_delete.append(i)
idx = idx.delete(index_delete)
periods = idx.size

idx_x_array = np.array(range(idx.size), dtype=np.int32)

str_vals = []
first_day_lines = []
counter = 0
if periods > 170:
    for s in idx._data:
        s = str(s)
        day = s[8:10]
        month = s[5:7]
        year = s[0:4]
        if day == '01':
            dotted_line_f = plt.Line2D((counter, counter), (0, 5), lw=2., marker='.',
                                       color='gray')
            first_day_lines.append(dotted_line_f)
            date_str = day+'/'+month+'/'+year
            str_vals.append(date_str)
        elif idx.dayofweek[counter]:
            date_str = day+'/'+month
            str_vals.append(date_str)
        else:
            str_vals.append('')
        counter +=1
if periods <= 170:
    for s in idx._data:
        s = str(s)
        day = s[8:10]
        month = s[5:7]
        year = s[0:4]
        if day == '01':
            dotted_line_f = plt.Line2D((counter, counter), (0, 5), lw=2., marker='.',
                                       color='gray')
            first_day_lines.append(dotted_line_f)
            date_str = day+'/'+month+'/'+year
            str_vals.append(date_str)
        else:
            date_str = day+'/'+month
            str_vals.append(date_str)
        counter +=1
plt.grid(True)

plt.xticks(idx_x_array, str_vals, rotation='vertical', fontsize=7)
values = []
for i in idx_x_array:
    values.append(0)

data= pd.DataFrame({('A','a'):values}, idx)
sns.set_context(context={"figure.figsize":(5,5)})
ab = sns.tsplot(data.T.values, idx_x_array)
ab.lines[0].set_color('red')
# x_len = len(ab.lines[0]._x)
ab.lines[0]._x = idx_x_array
dotted_line = plt.Line2D((1, 1), (0, 5), lw=2.,
                         ls='-.', marker='.',
                         markersize=1,
                         color='black',
                         markerfacecolor='black',
                         markeredgecolor='black',
                         alpha=0.5)
ab.add_line(dotted_line)
for line in first_day_lines:
    ab.add_line(line)

lines = ab.lines
init_focus = ab.lines[0]
index_focus = 0



bbox_props = dict(boxstyle="rarrow,pad=0.3", fc="pink", ec="b", lw=2)
horizontal_position = init_focus._x[index_focus]
plt.subplots_adjust(bottom=.30, left=.03, right=.97, top=.90, hspace=.35)

analysis_label = 'Analysis mode'
discovery_label = 'Discovery mode'


def chart_mode(event):
    global button_label
    global dotted_line
    global power
    global horizontal_position
    global index_focus
    global dotted_line
    global idx
    if button_label == analysis_label:
        index_focus = 0
        button_label = discovery_label
        plt.draw()
    elif button_label == discovery_label:
        index_focus = periods-1
        button_label = analysis_label
        plt.draw()
    bnext.label.set_text(button_label)
    horizontal_position = ab.lines[0]._x[index_focus]
    dotted_line = plt.Line2D((horizontal_position,horizontal_position), (0, 5), lw=5.,
                             ls='-.', marker='.',
                             markersize=1,
                             color='black',
                             markerfacecolor='black',
                             markeredgecolor='black',
                             alpha=0.5)
    ax.add_line(dotted_line)
    new_line = ax.lines.pop()
    ax.lines[1] = new_line

def export_csv(event):
    x_data = idx._data
    y_data = ab.lines[0]._y
    x_data_proc = []
    for x in x_data:
        x = str(x)
        day = x[8:10]
        month = x[5:7]
        year = x[0:4]
        date_str = day+'/'+month
        x_data_proc.append(date_str)
    y_data_proc = []
    for y in y_data:
        y_data_proc.append(int(y))
    with open('some.csv', 'wb') as f:
        writer = csv.writer(f)
        writer.writerows(izip(x_data_proc, y_data_proc))

button_label = analysis_label
axnext = plt.axes([0.1, 0.05, 0.1, 0.075])
bnext = Button(axnext, button_label)
bnext.on_clicked(chart_mode)

axexport = plt.axes([0.21, 0.05, 0.1, 0.075])
bexport = Button(axexport, 'export csv')
bexport.on_clicked(export_csv)

def on_keyboard(event):
    global power
    global horizontal_position
    global index_focus
    global dotted_line
    global idx
    if event.key == 'right':
        if index_focus < periods-1:
            index_focus+=1
        else:
            idx = idx + timedelta(days=1)
            index_focus+=1
    elif event.key == 'left':
        if index_focus > 0:
            index_focus-=1
    elif event.key == 'up':
        if index_focus < periods-5:
            index_focus+=5
    elif event.key == 'down':
        if index_focus > 5:
            index_focus-=5

    elif is_number(event.key):
        for i in range(len(ab.lines[0]._y[index_focus::])):
            ab.lines[0]._y[index_focus+i] = event.key

    horizontal_position = ab.lines[0]._x[index_focus]
    dotted_line = plt.Line2D((horizontal_position,horizontal_position), (0, 5), lw=2.,
                             ls='-.', marker='.',
                             markersize=1,
                             color='black',
                             markerfacecolor='black',
                             markeredgecolor='black',
                             alpha=0.5)
    ax.add_line(dotted_line)
    new_line = ax.lines.pop()
    ax.lines[1] = new_line
    fig.canvas.draw()
    plt.show()

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False
plt.gcf().canvas.mpl_connect('key_press_event', on_keyboard)
plt.show()

【问题讨论】:

    标签: python csv numpy matplotlib seaborn


    【解决方案1】:

    恐怕这段代码对我来说太长了。 尽管如此,还是有几个简单的方法可以帮助找到瓶颈:

    • 中断慢程序,查看堆栈跟踪;重复 5 次。 在您的情况下,这些将在 Qt4 等中有很多难以理解的调用, 但您可能会看到您的代码调用的内容很慢。

    • 好老print:添加例如print "%.3f %s" % (time.time() - t0, event.key)on_keyboard 中。 然后,注释掉绘图的东西,只打印,瞎跑:是花在绘图上的时间, 还是其他地方?

    另外,为什么Qt4Agg -- 和TkAgg 一样慢?
    另外,“当使用大日期范围时”是什么意思——多大?

    【讨论】:

      猜你喜欢
      • 2021-10-27
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      相关资源
      最近更新 更多