0

Recently, I am focusing on producing a time series graph. I read all the csv data to python by using pandas,which the time will be the index.

scrollbar is added as aid for presentation. I import Slider from matplotlib.widgets to produce it. And All looks fine.

However, I want to improve it. The graph now I produce is not bad. If I want to go into the datapoint I can just click the Slider bar.

However, is it possible to add a button to control the slider bar. What I mean is that can I add a right button. Once I click this right button, the whole graph will move right 5 datapoint( or 5 minutes as it is a time series model) And can I make a 'left' button too? Therefore, if I will go fast I can direct click the Slider bar. Then, If i wanna present it slow, I can just click the button?

Actually, I have read some information about 'button library'. However, I don't know how to use it to update the Slider.

Here is my code

df_BA = cs_66667_BS[['BidPrice','AskPrice']]
title_name = 'cs_66667_BS'

ax = df_BA.plot(title= title_name, fontsize= 10, figsize=(20, 10))
ax.set_xlabel('Date', fontsize= 15)
ax.set_ylabel('Price', fontsize= 15)
plt.subplots_adjust(left= 0.04, bottom= 0.25, right= 0.99, top= 0.95, wspace= 0, hspace= 0.1 )

x= df_BA.index.to_pydatetime()
x_min_index = 0
x_max_index = 1

x_min = x[0]
x_max = x[-1] - datetime.timedelta(minutes=4)
y_min = df_BA.BidPrice.min()
y_max = df_BA.AskPrice.max()

# timedelta
x_dt = datetime.timedelta(minutes=5)
axcolor = 'lightgoldenrodyellow'
axpos = plt.axes([0.05, 0.1, 0.9, 0.05], axisbg=axcolor)
slider_max = len(x) - x_max_index - 1

# Slider(axes, name, min, max)
spos = Slider(axpos, 'Pos', matplotlib.dates.date2num(x_min), matplotlib.dates.date2num(x_max))
# pretty date names
plt.gcf().autofmt_xdate()

def update(val):
    pos = spos.val
    xmin_time = matplotlib.dates.num2date(pos)
    xmax_time = matplotlib.dates.num2date(pos) + x_dt
    xmin_time = pos
    ax.axis([xmin_time, xmax_time, y_min, y_max])
    ########################################################
    fig.canvas.draw_idle()

spos.on_changed(update)

plt.show()
Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75

1 Answers1

2

You can easily add a matplotlib.widgets.Button to the plot, in the same way you added a matplotlib.widgets.Slider. You can then connect the button to a function forward() or backward() which will set the Slider to a new position.

Here is a complete working example which is hopefully close enough to your's (I did change some stuff though)

import matplotlib.pyplot as plt
import matplotlib.dates
from matplotlib.widgets import Slider, Button
import datetime
import pandas as pd
import numpy as np

rng = pd.date_range(datetime.datetime.now(), periods=340, freq='T')

data = {'BidPrice': np.random.random(340)*np.sin(np.arange(340)/30.),
        'AskPrice': np.random.random(340)*np.sin(np.arange(340)/30.-2) }
df_BA = pd.DataFrame(data, columns=['BidPrice','AskPrice'], index=rng)

ax = df_BA.plot(title= "Title", fontsize= 10, figsize=(10, 8))
ax.set_xlabel('Date', fontsize= 15)
ax.set_ylabel('Price', fontsize= 15)
plt.subplots_adjust(left= 0.04, bottom= 0.25, right= 0.99, top= 0.95, wspace= 0, hspace= 0.1 )

x= df_BA.index.to_pydatetime()

x_min = x[0]
x_max = x[0] + datetime.timedelta(minutes=20)
y_min = df_BA.BidPrice.min()
y_max = df_BA.AskPrice.max()
ax.set_xlim([x_min, x_max])
ax.set_ylim([y_min, y_max])

x_dt = datetime.timedelta(minutes=10)

axpos = plt.axes([0.2, 0.1, 0.58, 0.03], axisbg='w')
axpos1 = plt.axes([0.05, 0.1, 0.05, 0.03], axisbg='w')
axpos2 = plt.axes([0.93, 0.1, 0.05, 0.03], axisbg='w')

# Slider(axes, name, min, max)
spos = Slider(axpos, 'Pos', matplotlib.dates.date2num(x_min), matplotlib.dates.date2num(x[-1]))
spos.set_val(matplotlib.dates.date2num(x[0]))

button1 = Button(axpos1, '<', color='w', hovercolor='b')
button2 = Button(axpos2, '>', color='w', hovercolor='b')


def update(val):
    pos = spos.val
    xmin_time = matplotlib.dates.num2date(pos)
    xmax_time = matplotlib.dates.num2date(pos) + x_dt
    ax.set_xlim([xmin_time, xmax_time ])
    plt.gcf().canvas.draw_idle()

def forward(vl):
    pos = spos.val
    spos.set_val(matplotlib.dates.date2num( matplotlib.dates.num2date(pos) + datetime.timedelta(minutes=5) ))
def backward(vl):
    pos = spos.val
    spos.set_val(matplotlib.dates.date2num( matplotlib.dates.num2date(pos) - datetime.timedelta(minutes=5) ))

spos.on_changed(update)
button1.on_clicked(backward)
button2.on_clicked(forward)

plt.show() 
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712