Adding a secondary axis in Plotly Python - python

I'm working with a Dash graph object and I'm fairly new to it. I'm attempting to pass in a graph that has 2 scatter charts and a bar chart on the same figure but I'd like the bar chart (green) to be on it's own secondary y axis so it looks better than it does here:
Now from what I understand about Dash, I have to pass a go.Figure() object so I have a function which defines the data and the layout. I saw in the plotly documentation that you can use plotly express add secondary axis but I'm not sure how to do that within my frame work here. Any help would be greatly appreciated!
Here's my code:
def update_running_graph(n_intervals):
df = pd.read_csv(filename)
trace1 = go.Scatter(x=df['Timestamp'],
y=df['CLE'],
name='Crude',
mode='lines+markers')
trace2 = go.Scatter(x=df['Timestamp'],
y=df['y_pred'],
name='Model',
mode='lines+markers')
trace3 = go.Bar(x=df['Timestamp'],
y=df['ModelDiff'],
name='Diff',
)
data = [trace1, trace2,trace3]
layout = go.Layout(title='CLE vs Model')
return go.Figure(data=data, layout=layout)

To add a secondary y-axis in dash you could do the following:
def update_running_graph(n_intervals):
df = pd.read_csv(filename)
trace1 = go.Scatter(x=df['Timestamp'],
y=df['CLE'],
name='Crude',
mode='lines+markers',
yaxis='y1')
trace2 = go.Scatter(x=df['Timestamp'],
y=df['y_pred'],
name='Model',
mode='lines+markers',
yaxis='y1')
trace3 = go.Bar(x=df['Timestamp'],
y=df['ModelDiff'],
name='Diff',
yaxis='y2'
)
data = [trace1, trace2,trace3]
layout = go.Layout(title='CLE vs Model',
yaxis=dict(title='Crude and Model'),
yaxis2=dict(title='Moddel Difference',
overlaying='y',
side='right'))
return go.Figure(data=data, layout=layout)
you can add more y-axis they always need to have the form of yi with i the i-th axis. Then in the layout you can specify the layout of the i-th axis with yaxisi=dict(...).

This documentation page should be of use. Just modify to fit your code, since trace1 and trace2 appear to be on the same scale, just set trace3 to the secondary axis scale and you should be set. Below is an example with just only 2 but adding a third should not be too difficult.
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])
# Add traces
fig.add_trace(
go.Scatter(x=[1, 2, 3], y=[40, 50, 60], name="yaxis data"),
secondary_y=False,
)
fig.add_trace(
go.Scatter(x=[2, 3, 4], y=[4, 5, 6], name="yaxis2 data"),
secondary_y=True,
)
# Add figure title
fig.update_layout(
title_text="Double Y Axis Example"
)
# Set x-axis title
fig.update_xaxes(title_text="xaxis title")
# Set y-axes titles
fig.update_yaxes(title_text="<b>primary</b> yaxis title", secondary_y=False)
fig.update_yaxes(title_text="<b>secondary</b> yaxis title", secondary_y=True)
fig.show()
Cheers!

Related

Is there a way to set the values on a Y axis?

I'm trying to create a bar graph using two plots but the Y axis doesn't fit with the y values I have assigned to it (Percent Change). I don't see what I have done wrong when creating the bar graph because when I created a scatter graph with the same approach and assigned values it seemed to be working fine. The y axis should be showing 'percent change' that is 10 or higher. While it does so when a scatter graph is created, it doesn't show these values when creating the bar graph. Instead the bar graph shows the random percent change between 0 and 100 which is not in the assigned values table. Is there any way that I can fix this?
I've copied the code below.
import plotly.graph_objects as go
from plotly.subplots import make_subplots
trace1 = go.Bar(
x=df["Date"],
y=TopTesla["Percent Change"],
name='With Tesla',
text=TopTesla['text'],
marker=dict(
color='rgb(30,160,190)'
)
)
trace2 = go.Bar(
x=df["Date"],
y=TopNotTesla["Percent Change"],
name='Without Tesla',
text=TopNotTesla["text"],
marker=dict(
color='rgb(255,200,35)'
),
yaxis='y2',
offset=100,
showlegend=True
)
fig = make_subplots(specs=[[{"secondary_y": True}]])
fig.add_trace(trace1)
fig.add_trace(trace2,secondary_y=True)
fig['layout'].update(height = 1100, width = 1500,xaxis=dict(
tickangle=-90
))
plt.figure(figsize=[20,25])
iplot(fig)

Plotly deactivate x axis sorting

I want to plot a bar chart. On the x-axis are IDs of consultants. They range between 1000 and 2000. Each consultant has a specific number of customers (y-axis).
Now I want to plot a bar chart in plotly. But plotly orders the consultant IDs ascending and interprets them as integer, but they are not. They shall be ordered like the list I give plotly.
By the way in matplotlib the order is right.
trace1 = go.Bar(
x=consultants,
y=info[0,:]
)
trace2 = go.Bar(
x=consultants,
y=info[1,:],
)
trace3 = go.Bar(
x=consultants,
y=info[2,:]
)
trace4 = go.Bar(
x=consultants,
y=info[3,:]
)
data = [trace1, trace2, trace3, trace4]
layout = go.Layout(
barmode='stack',
xaxis=dict(
categoryorder='array',
categoryarray=consultants,
titlefont=dict(
size=18,
color='black'),
showticklabels=True,
tickfont=dict(
size=16,
color='black',
),
tickangle=20
),
yaxis=dict(
title='Number of customers',
titlefont=dict(
size=18,
color='black'),
showgrid=True,
showline=False,
showticklabels=True,
tickfont=dict(
size=16,
color='black')
),
)
fig = go.Figure(data=data, layout=layout)
py.iplot(fig, filename='stacked-bar')
The lastest version of Plotly now has a variable in the layout options to specify a categorical layout for the X axis:
fig.update_layout(
xaxis_type = 'category'
)
Interestingly Plotly seems to ignore categoryorder for integers but disabling of sorting can be achieved by passing type='category in xaxis in layout.
type ( enumerated : "-" | "linear" | "log" | "date" | "category" )
default: "-"
Sets the axis type. By default, plotly attempts to
determined the axis type by looking into the data of the traces that
referenced the axis in question.
import plotly
import plotly.graph_objs as go
import numpy as np
plotly.offline.init_notebook_mode()
consultants = [1, 3, 2, 5, 4]
info = np.random.randint(100, size=(5,5))
data = []
for i in range(len(info)):
data.append(go.Bar(x=consultants,
y=info[i,:]))
layout = go.Layout(barmode='stack',
xaxis=dict(type='category'),
yaxis=dict(title='Number of customers'))
fig = go.Figure(data=data, layout=layout)
plotly.offline.iplot(fig, filename='stacked-bar')

Plotly offline time series with multiple axis

I have a plotly offline chart with datetime and single y axis,now I want to add one more line in y axis.
original code:
from plotly.offline import download_plotlyjs,init_notebook_mode,plot
plot([Scatter(x=datetimefield,y=value1)],filename="plotly.html")
To add multiple I am tried to tweak the y parameter :
plot([Scatter(x=datecolumn,y=[value1,value2])],filename="plotly.html")
But this doesn't seems to be working.
x=datetime field is time series based
y=value1 & value 2 are two pandas columns
Note:- Two axis are in different datatype one is numeric other is percentage
How to tweak the y parameter in offline mode of plotly to have multiple axis.
Found solution:
from plotly.offline import download_plotlyjs,init_notebook_mode,plot
import plotly.graph_objs as go
trace1 = go.Scatter(
x=df.datetimecolumn,
y=df.value1)
trace2 = go.Scatter(
x=df.datetimecolumn,
y=df.value2)
data = [trace1, trace2]
layout = go.Layout(
xaxis=dict(
zeroline=True,
showline=True,
mirror='ticks',
gridcolor='#bdbdbd',
gridwidth=2,
zerolinecolor='#969696',
zerolinewidth=4,
linecolor='#636363',
linewidth=6
),
yaxis=dict(
zeroline=True,
showline=True,
mirror='ticks',
gridcolor='#bdbdbd',
gridwidth=2,
zerolinecolor='#969696',
zerolinewidth=4,
linecolor='#636363',
linewidth=6
)
)
fig = go.Figure(data=data, layout=layout)
plot(fig)

Histograms grouping by two criteria [python]

I have a dataset like this:
I need to plot this dataset based on two criteria: Churn and Cust_Value.
I can do it using seaborn:
sns.barplot(x="Cust_Value", y="value", hue="Churn", data=merged)
plt.show()
The result gives me:
How can I add all variables (value, age, reloads, calls, duration, sms, gprs, inactive) to the same graph as groups of bars?
for that kind of output i would recommend using plotly,
import plotly.plotly as py
import plotly.graph_objs as go
trace1 = go.Bar(
x=DF['Cust_Value'],
y=DF['value'],
name='value'
)
trace2 = go.Bar(
x=DF['Cust_Value'],
y=DF['age'],
name='age'
)
trace3 = go.Bar(
x=DF['Cust_Value'],
y=DF['calls'],
name='calls'
)
data = [trace1, trace2, trace3]
layout = go.Layout(
barmode='group'
)
fig = go.Figure(data=data, layout=layout)
py.iplot(fig, filename='grouped-bar')
sample output:
reference: https://plot.ly/python/bar-charts/
hope it helps!
if it does upvote :)
peace

Subplots with two y axes (each) - plotly and python/pandas

Are there guidelines on how to set up secondary Y-axes in python for plotly?
I am assinging axis style through an iterative loop, as follows:
all_plots = ['plot1','plot2'...'plot20']
fig = tools.make_subplots(rows=nrow, cols=ncol, shared_xaxes=False, shared_yaxes=False, subplot_titles=all_plots)
for i in all_plots:
fig['layout']['yaxis'+str(j)].update()
How does the assignment of y axes work?
If my subplot included, say, 4 rows and 5 columns for a total of 20 subplots, do I have to assume that plotly needs to receive odd and even numbers, meaning:
yaxis1 and yaxis2 for plot1
....
yaxis39 and yaxis40 for plot20
It is possible, to do this, but its not particularly intuitive. Take this example where I create a plot 2x2 subplots, and add a secondary y axis to the plot in position 2,2.
When you create a subplots, they are assigned y axes: "y1","y2","y3","y4" on the left side of each subplot. To a secondary y axes, you need to use fig['layout'].updateto create new axes "y5", "y6", "y7", "y8" which correspond to "y1","y2","y3","y4". So the bottom right subplot would have axes y4(right) and y8(left). In the example below, I only create a secondary y axis for the last plot, but expanding it to more/all the subplots is pretty straightforward.
It is important to note, that creating the secondary axes, and assigning it in trace5 doesn't automatically place it on the proper axes. You still have to manually assign it with fig['data'][4].update(yaxis='y'+str(8)) to plot it relative to the left axis.
fig = tools.make_subplots(rows=2, cols=2,subplot_titles=('Air Temperature', 'Photon Flux Density',
'Ground Temps','Water Table & Precip'))
fig['layout']['xaxis1'].update( range=[174, 256])
fig['layout']['xaxis3'].update(title='Day of Year', range=[174, 256])
fig['layout']['yaxis1'].update(title='Degrees C',range=[-5,30])
fig['layout']['yaxis2'].update(title='mmol m<sup>-2</sup> m<sup>-d</sup>', range=[0, 35])
fig['layout']['yaxis3'].update(title='Ground Temps', range=[0, 11])
fig['layout']['yaxis4'].update(title='depth cm', range=[-20, 0])
fig['layout']['yaxis8'].update(title='rainfall cm', range=[0, 1.6])
fig['layout'].update(showlegend=False, title='Climate Conditions')
# In this example, I am only doing it for the last subplot, but if you wanted to do if for all,
# Just change to range(1,5)
for k in range(4,5):
fig['layout'].update({'yaxis{}'.format(k+4): dict(anchor='x'+str(k),
overlaying='y'+str(k),
side='right',
)
})
trace1 = go.Scatter(
y=Daily['AirTC_Avg'],
x=Daily.index,
marker = dict(
size = 10,
color = 'rgba(160, 0, 0, .8)',),
error_y=dict(
type='data',
array=Daily_Max['AirTC_Avg']-Daily_Min['AirTC_Avg'],
visible=True,
color = 'rgba(100, 0, 0, .5)',
),
name = 'Air Temp'
)
trace2 = go.Bar(
y=Daily['PPFD']/1000,
x=Daily.index,
name='Photon Flux',
marker=dict(
color='rgb(180, 180, 0)'
),
yaxis='y2',
)
trace3 = go.Scatter(
y=Daily['Temp_2_5_1'],
x=Daily.index,
name='Soil Temp',
marker=dict(
color='rgb(180, 0, 0)'
),
yaxis='y3',
)
trace4 = go.Scatter(
y=Daily['Table_1']*100,
x=Daily.index,
name='Water Table',
marker=dict(
color='rgb(0, 0, 180)'
),
yaxis='y4',
)
trace5 = go.Bar(
y=Daily['Rain']/10,
x=Daily.index,
name='Rain',
marker=dict(
color='rgb(0, 100, 180)'
),
yaxis='y8',
)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
fig.append_trace(trace3, 2, 1)
fig.append_trace(trace4, 2, 2)
fig.append_trace(trace5, 2, 2)
## This part is important!!! you have to manually assing the data to the axis even
# though you do it when defining trace 5
fig['data'][4].update(yaxis='y'+str(8))
plot(fig, filename='FI_Climate')
Not an exact answer but I thought it might help...
I like to use pandas and cufflinks. Here is an example of how to plot two sets of data from one dataframe (df) on a graph using a secondary y axis. The data from each axis is displayed in different formats in this example (scatter and bar). The data is arranged into columns beforehand.
import pandas as pd
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode,plot,iplot
fig1 = df.iplot(kind='scatter', mode='lines+markers', x=['col1', 'col2'],
y=['col3', 'col4',],
asFigure=True)
fig2 = df.iplot(kind='bar', x=['col1', 'col2'],
y=['col3', 'col4', ],
secondary_y=['col5','col6'],asFigure=True)
fig2['data'].extend(fig1['data'])
The naming convention is y, y2, y3... y40, and you make the reference to the axis in the trace dict.
So your traces should be like...
trace0 = dict(
x = xvals,
y = yvals,
yaxis = 'y'
)
trace1 = dict(
x = x2vals,
y = y2vals,
yaxis = 'y2'
)
....
trace40 = dict(
x = x40vals,
y = y40vals,
yaxis = 'y40'
)

Categories

Resources