Python PyQT/Seaborn-交互式图表、键盘箭头控件和速度

Python PyQT/Seaborn-交互式图表、键盘箭头控件和速度,python,csv,numpy,matplotlib,seaborn,Python,Csv,Numpy,Matplotlib,Seaborn,我正在用seaborn软件包创建一个交互式图表。 这是一个简单的图表,日期在x轴上,值在y轴上从0到5 我可以用箭头键左右移动光标栏,用num键设置图表的y值(并将图表的y值及其时间戳导出到csv)。 然而,当使用较大的日期范围时,程序会变得异常缓慢。 我按箭头键将光标移动一个栏,但可能需要一到两秒钟才能做出反应。(按键控制由PyQT完成) 你知道我该怎么加快速度吗 请随意复制粘贴代码并在python中运行以查看程序: import matplotlib.pyplot as plt import

我正在用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()
导入matplotlib.pyplot作为plt
导入matplotlib
作为pd进口熊猫
从日期时间导入时间增量,日期
将numpy作为np导入
matplotlib.use('Qt4Agg')
导入seaborn作为sns
从matplotlib.widgets导入按钮
导入matplotlib.lines
从matplotlib.lines导入Line2D
导入csv
从itertools导入izip
日期=[]
值=[]
sns.set(style=“ticks”)
图=plt.图(1,图尺寸=(25,7))
图clf()
ax=图添加_子批次(111)
图canvas.draw()
plt.ylim(0,5)
水平位置=0
周期=365
idx=pd.DatetimeIndex(start='2010-01-01',freq='d',periods=periods)
索引_delete=[]
对于范围内的i(idx.size):
如果idx[i].dayofweek==6或idx[i].dayofweek==5:
索引_delete.append(i)
idx=idx.delete(index\u delete)
周期=idx.size
idx_x_数组=np.array(范围(idx.size),dtype=np.int32)
str_vals=[]
第一天\u行=[]
计数器=0
如果周期>170:
对于idx.\u数据中的s:
s=str(s)
天=秒[8:10]
月份=秒[5:7]
年份=秒[0:4]
如果日期==“01”:
虚线=plt.Line2D((计数器,计数器),(0,5),lw=2,marker=',
颜色(灰色)
第一天。附加(虚线)
日期=日+'/'+月+'/'+年
附加日期(日期)
elif idx.dayofweek[计数器]:
日期=日+'/'+月
附加日期(日期)
其他:
str_vals.append(“”)
计数器+=1
如果周期为0:
索引_焦点-=1
elif event.key==“向上”:
如果索引_焦点5:
索引_焦点-=5
elif是_编号(事件键):
对于范围内的i(len(ab.lines[0]。_y[索引\焦点::]):
ab.lines[0]。_y[index_focus+i]=事件键
水平位置=ab线[0]。\U x[索引焦点]
虚线=直线2D((水平位置,水平位置),(0,5),lw=2。,
ls='-',marker='''.',
markersize=1,
颜色='黑色',
markerfacecolor='black',
markeredgecolor='black',
α=0.5)
ax.添加线(虚线)
new_line=ax.lines.pop()
ax.line[1]=新的
图canvas.draw()
plt.show()
def是_编号:
尝试:
浮球
返回真值
除值错误外:
返回错误
plt.gcf().canvas.mpl\u connect(“键盘上的按键事件”)
plt.show()

恐怕这段代码太长了,我无法理解。 尽管如此,有两种简单的方法可以帮助找到瓶颈:

  • 中断慢速程序,并查看堆栈跟踪;重复5次。 在您的情况下,在Qt4中会有很多无法理解的呼叫等。, 但是你可以看到你的代码在调用什么,这太慢了

  • 好的旧
    打印
    :在键盘上的
    中添加例如
    打印“%.3f%s”%(time.time()-t0,event.key)
    。 然后,注释掉绘图内容,只打印,盲目运行:是在绘图上花费的时间, 还是别的地方

另外,为什么
Qt4Agg
--是
TkAgg
一样慢?

还有,“当使用大的日期范围时”意味着什么——有多大?

恐怕这段代码太长了,我无法仔细阅读。 尽管如此,有两种简单的方法可以帮助找到瓶颈:

  • 中断慢速程序,并查看堆栈跟踪;重复5次。 在您的情况下,在Qt4中会有很多无法理解的呼叫等。, 但是你可以看到你的代码在调用什么,这太慢了

  • 好的旧
    打印
    :在键盘上的
    中添加例如
    打印“%.3f%s”%(time.time()-t0,event.key)
    。 然后,注释掉绘图内容,只打印,盲目运行:是在绘图上花费的时间, 还是别的地方

另外,为什么
Qt4Agg
--是
TkAgg
一样慢?
还有,“当使用较大的日期范围时”意味着什么——多大