6

I'm beginning to learn more about plotly and pandas and have a multivariate time series I wish to plot and interact with using plotly.express features. I also want my plot to a horizontal scrollbar so that the initial plot is for a pre-specified initial time interval. Here's my example involving three time series along with 100K time points:

import plotly.express as px
import numpy as np
import pandas as pd

np.random.seed(123)
e = np.random.randn(100000,3)  
df=pd.DataFrame(e, columns=['a','b','c'])

df['x'] = df.index
df_melt = pd.melt(df, id_vars="x", value_vars=df.columns[:-1])
fig=px.line(df_melt, x="x", y="value",color="variable")
fig.show()

enter image description here

(For my ultimate purposes, the time series will be larger--likely 40 to 70 time series in 900K+ time points.)

This creates a graph with which I can interact using plotly.express features like zooming, panning, rectangle selection, etc.

Is there a way I can augment this so that the initial plot shows merely the first 500 time points and a scroll bar permits me to investigate what happens as time increases?

Using Mac OS 10.15.4 and Python 3.7 with IDLE. I wish to create this in IDLE and not in a Jupyter notebook environment.

vestland
  • 55,229
  • 37
  • 187
  • 305
fishbacp
  • 1,123
  • 3
  • 14
  • 29
  • Very nice--thank you so much. For my own series, the number of time points is very large (~900K) and there are typically 40-70 series. I assume the amount of time required to create the figure in my web browser is really just a function of my machine and there's nothing I can do to speed up the process other than downsample/decimate? – fishbacp May 15 '20 at 16:36
  • @hfshbacp Happy to help! Would you consider marking my suggestion as the accepted answer? Regarding time and speed, please consider posting a separate question about that. I would very much like to see an answer on that myself – vestland May 26 '20 at 07:36

2 Answers2

9

The easiest way is to add the following to your setup:

fig.update_layout(xaxis=dict(rangeslider=dict(visible=True),
                             type="linear"))

And you'll get:

enter image description here

This will enable you to both subset and pan the original figure:

enter image description here

Complete code:

import plotly.express as px
import numpy as np
import pandas as pd

np.random.seed(123)
e = np.random.randn(100000,3)  
df=pd.DataFrame(e, columns=['a','b','c'])

df['x'] = df.index
df_melt = pd.melt(df, id_vars="x", value_vars=df.columns[:-1])
fig=px.line(df_melt, x="x", y="value",color="variable")

# Add range slider
fig.update_layout(xaxis=dict(rangeslider=dict(visible=True),
                             type="linear")
)

fig.show()
vestland
  • 55,229
  • 37
  • 187
  • 305
  • 2
    Any way to set the initial width of the slider? By default, it spans the whole plot, and I can only find a way to use buttons to set width for date oriented plots.. – Sharat Jun 19 '21 at 01:26
3

Use plotly.graphing_objects to use plotly offline

You could also use plotly.graphing_objects as follows.

Quoting the following example from the official documentation.

import plotly.graph_objects as go

import pandas as pd

# Load data
df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
df.columns = [col.replace("AAPL.", "") for col in df.columns]

# Create figure
fig = go.Figure()

fig.add_trace(
    go.Scatter(x=list(df.Date), y=list(df.High)))

# Set title
fig.update_layout(
    title_text="Time series with range slider and selectors"
)

# Add range slider
fig.update_layout(
    xaxis=dict(
        rangeselector=dict(
            buttons=list([
                dict(count=1,
                     label="1m",
                     step="month",
                     stepmode="backward"),
                dict(count=6,
                     label="6m",
                     step="month",
                     stepmode="backward"),
                dict(count=1,
                     label="YTD",
                     step="year",
                     stepmode="todate"),
                dict(count=1,
                     label="1y",
                     step="year",
                     stepmode="backward"),
                dict(step="all")
            ])
        ),
        rangeslider=dict(
            visible=True
        ),
        type="date"
    )
)

fig.show()

enter image description here

CypherX
  • 7,019
  • 3
  • 25
  • 37
  • You do *not* need to use an on-line API to apply the powers of plotly express. Plotly express and plotly_graphobjects just have a bit different use-cases. And you can perfectly well combine the usage of both in the same figure. – vestland May 13 '20 at 22:55
  • 1
    Perhaps I was mistaken then. I though `plotly.express` requires an api access. I will check back later and update the statement. Thank you. – CypherX May 13 '20 at 22:58
  • 1
    No problem! Perhaps start by taking a look at [px.express](https://plotly.com/python/plotly-express/). One of the most imortant things you'll find there is that express works very good with long data, whereas graphobjects arguably works better with data of a wide format where you have unique categories of values in a column. I actually wrote a little piece on this yesterday in my answer to [this post](https://stackoverflow.com/questions/61747526/plotly-how-to-output-multiple-line-charts-in-single-figure/61749024#61749024) – vestland May 13 '20 at 23:03
  • 1
    On a side note I've gotta say I really like your answer [here](https://stackoverflow.com/questions/61693014/how-to-hide-plotly-yaxis-title-in-python/61693190#61693190). The concept of dict flattening was unknown to me until I saw that. – vestland May 13 '20 at 23:07
  • @vestland Thank you for sharing the resources. :) – CypherX May 26 '20 at 07:01
  • No problem! Plotly has got greats docs, but I still feel that the real gems are spread out all over the place. And cufflinks, iplot, express and graph_objects still leaves me quite confused from time to time... – vestland May 26 '20 at 07:05
  • 1
    @vestland Here is a another gem: [plotly/jupyter-dash](https://github.com/plotly/jupyter-dash/blob/master/README.md). – CypherX May 26 '20 at 07:24
  • Yeah, that almost looks too good to be true for a JupyterLab fan! Have you tried it out yet? – vestland May 26 '20 at 07:35
  • No, not yet. Got to know about it yesterday. Will try out soon. But, it sure looks impressive. – CypherX May 26 '20 at 07:48
  • Looks fantastic! But I'm a bit concerned with what seems to be an unstability with regards to plotly and JupyterLab. The latest versions for both don't seem to work very well together. – vestland May 26 '20 at 08:41