Plotly Express Overlay Two Line Graphs - python

I know that it is easy to overlay plots using Plotly Go.
import plotly.graph_objects as go
fig = go.Figure()
fig.add_traces([go.Scatter(x=[1,2,3], y=[2,1,2]),
go.Scatter(x=[1,2,3], y=[2,1,2]),
go.Scatter(x=[1,2,3], y=[1,1,2])])
fig.show()
However, I would like to accomplish same task using Poltly Express. Is there a way to accomplish such a task in Plotly Express?

You can do it with add_traces
import pandas as pd
import numpy as np
import plotly.express as px
data = {'x':[1,2,3], 'y':range(3)}
df1 = pd.DataFrame(data)
data = {'x':[4,5,6], 'y':range(4,7)}
df2 = pd.DataFrame(data)
fig1 = px.line(df1, x='x', y='y', color_discrete_sequence=['red'])
fig2 = px.line(df2, x='x', y='y', labels='green', color_discrete_sequence=['green'])
fig1.add_traces(
list(fig2.select_traces())
)
name = ['red','green']
for i in range(len(fig1.data)):
fig1.data[i]['name'] = name[i]
fig1.data[i]['showlegend'] = True
fig1.show()
However, I prefer to use go plots, which are easier.

Related

Plotly: how to draw two linecharts with two dataframes with colors [duplicate]

I would like to create a subplot with 2 plot generated with the function plotly.express.line, is it possible? Given the 2 plot:
fig1 =px.line(df, x=df.index, y='average')
fig1.show()
fig2 = px.line(df, x=df.index, y='Volume')
fig2.show()
I would like to generate an unique plot formed by 2 subplot (in the example fig1 and fig2)
Yes, you can build subplots using plotly express. Either
1. directly through the arguments facet_row and facet_colums (in which case we often talk about facet plots, but they're the same thing), or
2. indirectly through "stealing" elements from figures built with plotly express and using them in a standard make_subplots() setup with fig.add_traces()
Method 1: Facet and Trellis Plots in Python
Although plotly.express supports data of both wide and long format, I often prefer building facet plots from the latter. If you have a dataset such as this:
Date variable value
0 2019-11-04 average 4
1 2019-11-04 average 2
.
.
8 2019-12-30 volume 5
9 2019-12-30 volume 2
then you can build your subplots through:
fig = px.line(df, x='Date', y = 'value', facet_row = 'variable')
Plot 1:
By default, px.line() will apply the same color to both lines, but you can easily handle that through:
fig.update_traces(line_color)
This complete snippet shows you how:
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
df = pd.DataFrame({'Date': ['2019-11-04', '2019-11-04', '2019-11-18', '2019-11-18', '2019-12-16', '2019-12-16', '2019-12-30', '2019-12-30'],
'variable':['average', 'volume', 'average', 'volume', 'average','volume','average','volume'],
'value': [4,2,6,5,6,7,5,2]})
fig = px.line(df, x='Date', y = 'value', facet_row = 'variable')
fig.update_traces(line_color = 'red', row = 2)
fig.show()
Method 2: make_subplots
Since plotly express can do some pretty amazing stuff with fairly complicated datasets, I see no reason why you should not stumple upon cases where you would like to use elements of a plotly express figure as a source for a subplot. And that is very possible.
Below is an example where I've built to plotly express figures using px.line on the px.data.stocks() dataset. Then I go on to extract some elements of interest using add_trace and go.Scatter in a For Loop to build a subplot setup. You could certainly argue that you could just as easily do this directly on the data source. But then again, as initially stated, plotly express can be an excellent data handler in itself.
Plot 2: Subplots using plotly express figures as source:
Complete code:
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
from plotly.subplots import make_subplots
df = px.data.stocks().set_index('date')
fig1 = px.line(df[['GOOG', 'AAPL']])
fig2 = px.line(df[['AMZN', 'MSFT']])
fig = make_subplots(rows=2, cols=1)
for d in fig1.data:
fig.add_trace((go.Scatter(x=d['x'], y=d['y'], name = d['name'])), row=1, col=1)
for d in fig2.data:
fig.add_trace((go.Scatter(x=d['x'], y=d['y'], name = d['name'])), row=2, col=1)
fig.show()
There is no need to use graph_objects module if you have just already generated px figures for making subplots. Here is the full code.
import plotly.express as px
import pandas as pd
from plotly.subplots import make_subplots
df = px.data.stocks().set_index('date')
fig1 = px.line(df[['GOOG', 'AAPL']])
fig2 = px.line(df[['AMZN', 'MSFT']])
fig = make_subplots(rows=2, cols=1)
fig.add_trace(fig1['data'][0], row=1, col=1)
fig.add_trace(fig1['data'][1], row=1, col=1)
fig.add_trace(fig2['data'][0], row=2, col=1)
fig.add_trace(fig2['data'][1], row=2, col=1)
fig.show()
If there are more than two variables in each plot, one can use for loop also to add the traces using fig.add_trace method.
From the documentation, Plotly express does not support arbitrary subplot capabilities. You can instead use graph objects and traces (note that go.Scatter is equivalent):
import pandas as pd
from plotly.subplots import make_subplots
import plotly.graph_objects as go
## create some random data
df = pd.DataFrame(
data={'average':[1,2,3], 'Volume':[7,3,6]},
index=['a','b','c']
)
fig = make_subplots(rows=1, cols=2)
fig.add_trace(
go.Scatter(x=df.index, y=df.average, name='average'),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=df.index, y=df.Volume, name='Volume'),
row=1, col=2
)
fig.show()

LIne graph using plotly

With this script , it is open 2 dashboards and so 2 graphs
How i can modify it to see all on the same graph ?
dataframe:
df = pd.DataFrame( df_abs.to_numpy()[:, 1:].T).reset_index().melt(id_vars="index")
fig = px.line(df, x="index", y="value", color="variable")
fig.show()
script dot plotly:
df_abs = pd.DataFrame(df_abs.loc[outlier].iloc[1:]).reset_index().melt(id_vars="index")
fig = px.line(df_abs, x="index", y="value", color="variable")
fig.show()
df = pd.DataFrame( df_abs.to_numpy()[:, 1:].T).reset_index().melt(id_vars="index")
fig = px.line(df, x="index", y="value", color="variable")
fig.show()
You need to use plotly.graph_objects instead of plotly.express.
plotly.express is great for quick plots but it is somewhat limited compared to plotly.graph_objects.
Here is a dummy example using 2 dataframes to make it similar to your case.
import plotly.graph_objects as go
import plotly.express as px
df1 = px.data.gapminder().query("country in ['Canada']")
df2 = px.data.gapminder().query("country in ['Italy']")
fig = go.Figure()
fig.add_trace(go.Scatter(x=df1["lifeExp"], y=df1["gdpPercap"], mode='lines', name='Canada'))
fig.add_trace(go.Scatter(x=df2["lifeExp"], y=df1["gdpPercap"], mode='lines', name='Italy'))
fig.show()

Plotly python add annotation to display all column values at every point

I am trying to plot all column values at each point when we hover over a data point in plotly
My code is as follows
import plotly.graph_objects as go
import plotly.io as pio
from plotly.subplots import make_subplots
import pandas as pd
# data
pio.templates.default = "plotly_white"
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
df_s = df[['Date','AAPL.Open','AAPL.High','AAPL.Low','dn','mavg'
]]
df_s = df_s.set_index('Date')
df_s.tail()
cols = df_s.columns
ncols = len(cols)
# subplot setup
fig = make_subplots(rows=ncols, cols=1, shared_xaxes=True)
for i, col in enumerate(cols, start=1):
fig.add_trace(go.Scatter(x=df_s[col].index, y=df_s[col].values, name=df_s[col].name), row=i, col=1)
fig.update_layout(
autosize=False,
width=1200,
height=800,)
fig.show()
Currently when I hover over the datapoint it shows value for that column alone. I am interested in seeing
Values for 'Date','AAPL.Open','AAPL.High','AAPL.Low','dn','mavg' these columns at a particular row whenever I hover over anyplot
I tried add_annotations with no luck. Is there a way of doing it? Thank you in advance
As #Marco_CH pointed out, this exact feature doesn't exist in Plotly. However, you can try using a unified hovermode on the x-axis so there is only one hoverbox, and remove the date from each hovertemplate since it's already shown at the top of the hoverbox.
import pandas as pd
import plotly.express as px
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
df1 = df.melt(id_vars=['Date']+list(df.keys()[5:]), var_name='AAPL')
fig = px.line(df1, x='Date', y='value', color='AAPL' )
## remove date from each hovertemplate
for fig_data in fig.data:
fig_data['hovertemplate'] = fig_data['hovertemplate'].replace("<br>Date=%{x}","")
fig.update_layout(hovermode="x unified")
fig.show()
No, this doesn't work. There is an open issue for this:
https://github.com/plotly/plotly.js/issues/4755
And it doesn't seem that this will come soon. You have to decide between your way and something like:
import pandas as pd
import plotly.express as px
pio.templates.default = "plotly_white"
df_s = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
df_s = df_s.melt(id_vars=["Date"]+list(df.keys()[5:]), var_name="AAPL")
fig = px.line(df_s, x="Date", y="value", color="AAPL")
fig.update_layout(
autosize=False,
width=1200,
height=800,
hovermode="x")
fig.show()
Output:

Plotly time series multiplots

I need help with plotly - plotting time series interactive charts with multiple lines in each subplot. My data looks like this:
import pandas as pd
df1 = pd.DataFrame(np.random.randint(100, size=(100,6)), columns=['A_red', 'A_blue', 'B_red', 'B_blue', 'C_red', 'C_blue'])
Next I want to do:
import plotly.express as px
fig1 = px.line(df, y=['A_red', 'A_blue'], color=['red', 'blue'])
fig2 = px.line(df, y=['B_red', 'B_blue'], color=['red', 'blue'])
fig3 = px.line(df, y=['C_red', 'C_blue'], color=['red', 'blue'])
figs = [fig1, fig2, fig3]
figs.show()
I cant get any plot to load in spyder (inline or in the plots tab), also how do I map colors to different lines?
Thanks
Spyder doesn't support interactive graphs. You have 2 options to show the plots: either show them in a browser, or display them as static plots. To render them in a browser where they will be interactive:
import plotly.io as pio
pio.renderers.default = 'browser'
To render them in the Spyder plots pane as a static chart:
import plotly.io as pio
pio.renderers.default = 'svg'
You need to delete the color argument from the px.line() calls or it will throw an error. Given the way your data is formatted, you won't be able to easily use the color argument. To change the colors of the lines:
fig1 = px.line(df, y=['A_red', 'A_blue'])
fig1.data[0].line.color = 'green'
fig1.data[1].line.color = 'purple'
fig1.show()
Not that you asked for it, but in order to get
figs = [fig1, fig2, fig3]
figs.show()
to work, you will need to do the following:
figs = [fig1, fig2, fig3]
for fig in figs:
fig.show()
To plot all 3 in a single figure you will first need to transform the data from wide to long:
df = pd.DataFrame(np.random.randint(100, size=(100,6)),
columns=['A_red', 'A_blue', 'B_red', 'B_blue', 'C_red', 'C_blue'])
df['x'] = df.index
df_long = df.melt(id_vars='x', var_name='letter')
df_long['group'] = df_long.letter.str.split('_', expand=True)[1]
df_long['letter'] = df_long.letter.str.split('_', expand=True)[0]
Then you can do the following:
facet_fig = px.line(df_long, y='value', x='x', color='group', facet_row='letter')

How to add several graphs to a single tab using plotly express with python

I have a script that producing 5 different graphs that I want to present in one web page.
I use python with plotly express and define pio.renderers.default = "browser".
The problem is that each graph is open in a new tab, and I want only one tab that I could share.
My script contains two separate data frames:
import pandas as pd
import plotly.express as px
import plotly.io as pio
pio.renderers.default = "browser"
df1=pd.read_csv('data1.csv')
df2=pd.read_csv('data2.csv')
fig = px.bar(df1,x1, y1,color='a',barmode='group')
fig.show()
fig = px.line(df2,x2, y2,color='b')
fig.show()
OK, you need to use plotly.subplots.make_subplots. I don't have your data, so I will use a simple data from plotly in the following code:
import plotly.express as px
from plotly.subplots import make_subplots
df = px.data.gapminder().query("country == 'Canada'")
fig1 = px.bar(df, x='year', y='pop')
fig2 = px.line(df, x="year", y="lifeExp", title='Life expectancy in Canada')
fig = make_subplots(rows=2, cols=1, shared_xaxes=False)
fig.add_trace(fig1['data'][0], row=1, col=1)
fig.add_trace(fig2['data'][0], row=2, col=1)
fig.show()
This will generate the following graph:
Side Note: Plotly.express shows figure in the browser by default, you don't have to specify it.

Categories