0

I am trying to make an interactive time serie visualization using plotly and jupyter notebook. I want to have a simple plot where I can filter the index of a dataframe using plotly and ipywidget and store the new index I have. But, I have no idea how to do so. I am investigating the documentation without any success. What I am doing so far :

import pandas as pd
import numpy as np
import plotly.graph_objs as go
from ipywidgets import interactive

index = pd.date_range(start='2020-01-01', end='2020-01-15', freq='D')
timeserie = pd.DataFrame(np.random.normal(0,1,size=index.size), index=index, columns=['sensor'])
fig = go.FigureWidget([
    go.Scatter(
        x=timeserie.index.values,
        y=timeserie.values,
        mode='markers'
    )
])
 
def update_training_dataset(index_min, index_max, sensor):
    scatter = fig.data[0]
    index = timeserie.loc[(timeserie.index >= index_min) & (timeserie.index <= index_max)].index
    sensor_value = timeserie.loc[scatter.x, sensor].values
    with fig.batch_update():
        fig.layout.yaxis.title = sensor
        scatter.x = index
        scatter.y = sensor_value
 
interactive(update_training_dataset, index_min=index, index_max=index, sensor=timeserie.columns)

But, it leads to a strange error.. KeyError : "None of [Int64Index([15778368000000000000, ... are in the [index]" This is weird as the index of my timeserie has datetimeindex as type. This code would lead to updating the dataframe according to the values of sensor, index_min, index_max that the user set. Also, I note that the date are provided in a select widget... I would love to have a date picker here. Can someone help me ? Provide any code that I can get some insights from ? Thank you :)

EDIT

The solution is provided below thanks to Serge :)

fig = go.FigureWidget([
    go.Scatter(
        x=timeserie.index,
        y=timeserie.values,
        mode='markers'
    )
])
 
def update_training_dataset(index_min, index_max, Sensor):
    scatter = fig.data[0]
    index = timeserie.loc[(timeserie.index >= index_min) & (timeserie.index <= index_max)].index
    sensor_value = timeserie.loc[scatter.x, Sensor].values
    with fig.batch_update():
        fig.layout.yaxis.title = Sensor
        scatter.x = index
        scatter.y = sensor_value
 
        
date_picker_max = DatePicker(
    description='End date',
    disabled=False,
    value = index.max()
)
 
date_picker_min = DatePicker(
    description='Start date',
    disabled=False,
    value = index.min()
)
 
interact(
    update_training_dataset, 
    index_min=date_picker_min, 
    index_max=date_picker_max, 
    Sensor=timeserie.columns
)

I am still working on a way to have hours:minutes:seconds in the date picker.

EDIT 2 By the way, no need to use interact instead of interactive : they seem to support widgets as parameters. Also, you need to import ipydatetime as below to get datetime picker.

# usual imports
from ipydatetime import DatetimePicker

fig = go.FigureWidget([
    go.Scatter(
        x=timeserie.index,
        y=timeserie.values,
        mode='markers'
    )
])
 
def update_training_dataset(index_min, index_max, Sensor):
    scatter = fig.data[0]
    index = timeserie.loc[(timeserie.index >= index_min) & (timeserie.index <= index_max)].index
    sensor_value = timeserie.loc[scatter.x, Sensor].values
    with fig.batch_update():
        fig.layout.yaxis.title = Sensor
        scatter.x = index
        scatter.y = sensor_value
 
        
date_picker_max = DatetimePicker(
    description='End date',
    disabled=False,
    value = index.max()
)
 
date_picker_min = DatetimePicker(
    description='Start date',
    disabled=False,
    value = index.min()
)
 
interact(
    update_training_dataset, 
    index_min=date_picker_min, 
    index_max=date_picker_max, 
    Sensor=timeserie.columns
)
2
  • How is your function interactive defined? Or where is it defined? Commented Nov 30, 2020 at 16:39
  • Hi, thanks for your remark. I have edited the post so that you can look at the imports. Commented Nov 30, 2020 at 16:46

1 Answer 1

1

Actually, your code is all good. You did a simple mistake in the definition of fig. Try the following

fig = go.FigureWidget([
    go.Scatter(
        x=timeserie.index,
        y=timeserie.values,
        mode='markers'
    )
])
 
def update_training_dataset(index_min, index_max, sensor):
    scatter = fig.data[0]
    index = timeserie.loc[(timeserie.index >= index_min) & (timeserie.index <= index_max)].index
    sensor_value = timeserie.loc[scatter.x, sensor].values
    with fig.batch_update():
        fig.layout.yaxis.title = sensor
        scatter.x = index
        scatter.y = sensor_value
 
interactive(update_training_dataset, index_min=index, index_max=index, sensor=timeserie.columns)

You simly made the error of defining x=timeserie.index.values when it actually should be x=timeserie.index.

The result is fine when this is changed.

Sign up to request clarification or add additional context in comments.

5 Comments

Ah okay. This solve my error. But, do you have any idea about having a date picker instead of a select ? That would help me a lot :)
To do that you should use interact instead of interactive
Thanks, I will see and provide a code soon :)
I provided the solution with interact. Thank you so mush Serge ! I am now trying to add hours:minutes:seconds in the date picker. Hope to provide a code for this need soon :)
I added some modifications to the solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.