How to add caption & subtitle using plotly method in python - python

I'm trying to plot a bar chart using plotly and I wanted to add a caption and subtitle.(Here you can take any example of your choice to add caption and subtitle)
My code for plotting the bar chart:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Bar(x=["Apple", 'Mango', 'Banana'], y=[400, 300, 500]))
fig.show()

Plotly takes your string and passes it as HTML. Adding HTML in the title string or X axis string lets you put in some quick subtitles/captions in both ploty graph objects and plotly express.
<br> is a line break, and <sup> is superscript, which lets you quickly make a smaller subtitle or caption.
graph objects:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Bar(x=["Apple", 'Mango', 'Banana'], y=[400, 300, 500]))
fig.update_layout(
title=go.layout.Title(
text="Plot Title <br><sup>Plot Subtitle</sup>",
xref="paper",
x=0
),
xaxis=go.layout.XAxis(
title=go.layout.xaxis.Title(
text="Fruits<br><sup>Fruit sales in the month of January</sup>"
)
)
)
fig.show()
plotly express:
import plotly.express as px
fig = px.bar(
x=["Apple", 'Mango', 'Banana'],
y=[400, 300, 500],
title = "Plot Title <br><sup>Plot Subtitle</sup>",
labels = {'x':"Fruits<br><sup>Fruit sales in the month of January</sup>",
'y':'count'}
)
fig.show()
figure:

Use fig.update_layout(title_text='Your title') for your caption. There's no built-in option for subtitles. But you can get the desired effect by moving the x-axis labels to the top and at the same time insert an annotation at the bottom right. I've tried with other y-values as well, but there doesn't seem to be a way to get the annotations outside the plot itself. You could also change the fonts of the caption and subtitle to make them stand out from the rest of the labels.
Plot:
Code:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Bar(x=["Apple", 'Mango', 'Banana'], y=[400, 300, 500]))
fig.update_layout(title=go.layout.Title(text="Caption", font=dict(
family="Courier New, monospace",
size=22,
color="#0000FF"
)))
fig.update_layout(annotations=[
go.layout.Annotation(
showarrow=False,
text='Subtitle',
xanchor='right',
x=1,
xshift=275,
yanchor='top',
y=0.05,
font=dict(
family="Courier New, monospace",
size=22,
color="#0000FF"
)
)])
fig['layout']['xaxis'].update(side='top')
fig.show()

Maybe something like this?
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Bar(x=["Apple", 'Mango', 'Banana'], y=[400, 300, 500]))
fig.update_layout(
title=go.layout.Title(
text="Plot Title",
xref="paper",
x=0
),
xaxis=go.layout.XAxis(
title=go.layout.xaxis.Title(
text="x Axis",
font=dict(
family="Courier New, monospace",
size=18,
color="#7f7f7f"
)
)
),
yaxis=go.layout.YAxis(
title=go.layout.yaxis.Title(
text="y Axis",
font=dict(
family="Courier New, monospace",
size=18,
color="#7f7f7f"
)
)
)
)
fig.show()

Related

Change plotly express "color" variable with button

I would like to create a plotly plot where I can change the value of the plotly express color argument via a button. I am using plotly.express.scatter for this.
For example, the initial plot shown is px.scatter(df, "sepal_length", "sepal_width", color="species"). Changing from "species" to "petal length" in a dropdown menu would update the plot so that instead color="petal_length". If it makes a difference, "species" uses the default discrete color sequence while "petal_length" uses the default continuous color scale.
The code I have so far makes the initial plot and dropdown buttons, but choosing the buttons has no effect. I don't understand how to get the plotly express color argument passed through this Plotly.update interface.
import plotly.express as px
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv")
fig = px.scatter(df, "sepal_length", "sepal_width", color="species")
fig.update_layout(
updatemenus=[
dict(
buttons=list([
dict(
args=["color", "species"],
label="species",
method="update"
),
dict(
args=["color", "petal_length"],
label="petal length",
method="update"
),
]),
showactive=True,
x=0.05,
xanchor="left",
y=1.06,
yanchor="top"
),
]
)
fig.update_layout(
annotations=[
dict(text="color", x=0.015, xref="paper", y=1.05, yref="paper",
align="left", showarrow=False),
])
fig.show()
For color='species', three graphs are internally created for each categorical variable. And color='petal_length' consists of a single graph data. So, it is possible to handle this by setting the drop-down to show/hide the graph. The actual code reuses the data created by express.scatter. The data for each graph will be configured in a graph object; three will be shown and one will be hidden. Set the button to restyle as a function of the button.
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv")
fig1 = px.scatter(df, "sepal_length", "sepal_width", color="species")
fig2 = px.scatter(df, "sepal_length", "sepal_width", color="petal_length")
fig = go.Figure()
fig.add_trace(go.Scatter(fig1.data[0], visible=True))
fig.add_trace(go.Scatter(fig1.data[1], visible=True))
fig.add_trace(go.Scatter(fig1.data[2], visible=True))
fig.add_trace(go.Scatter(fig2.data[0], visible=False))
fig.update_layout(
updatemenus=[
dict(
buttons=list([
dict(
args=["visible", [True,True,True,False]],
label="species",
method="restyle"
),
dict(
args=["visible", [False,False,False,True]],
label="petal length",
method="restyle"
),
]),
showactive=True,
x=0.05,
xanchor="left",
y=1.2,
yanchor="top"
),
]
)
fig.update_layout(
annotations=[
dict(text="color", x=0.01, xref="paper", y=1.16, yref="paper",
align="left", showarrow=False),
])
fig.update_layout(xaxis_title_text='sepal_length', yaxis_title_text='sepal_width', legend_title_text='species')
fig.show()

Plotly: How to manually assign bar colors to categorical lables in go.bar()

I have a bar plot, with three bars that I am constructing from a dictionary. I am trying to map the individual bars to specific colors, based on the barname, not the value of the bar. I have been trying to find an answer for this for quite some time but am only finding answers related to mapping colors to the value of the bars, and not the specific bar name.
There must be an easy way to do this in plotly graph objects.
Here is some sample code illustrating the problem.
import plotly.graph_objects as go
tensions = {
'Supportive': 39,
'Neutral': 27,
'Resistant': 34
}
items = tensions.items()
x = [item[0] for item in items]
y = [item[1] for item in items]
fig = go.Figure()
fig.add_trace(
go.Bar(
x=x,
y=y,
width=0.2,
)
)
fig.update_layout(
template='simple_white',
paper_bgcolor='#F9F9FA',
plot_bgcolor='#F9F9FA',
height=200,
margin=dict(
t=20, b=20, l=60, r=40
),
)
fig.update_yaxes(
tickformat=',.0%',
)
This produces the figure below.
What I want is to make the Supportive bar green, the Neutral bar yellow and the Resistant bar red. How can I accomplish this?
You can pass an array of colors to the marker_color parameter in go.Bar, using a dictionary to map each category to your desired color (similar to the example in the documentation here). For example:
import plotly.graph_objects as go
tensions = {
'Supportive': 39,
'Neutral': 27,
'Resistant': 34
}
color_map = {
'Supportive': 'green',
'Neutral': 'yellow',
'Resistant': 'red'
}
items = tensions.items()
x = [item[0] for item in items]
y = [item[1] for item in items]
colors = [color_map[category] for category in x]
fig = go.Figure()
fig.add_trace(
go.Bar(
x=x,
y=y,
marker_color=colors,
width=0.2,
)
)
fig.update_layout(
template='simple_white',
paper_bgcolor='#F9F9FA',
plot_bgcolor='#F9F9FA',
height=200,
margin=dict(
t=20, b=20, l=60, r=40
),
)
fig.update_yaxes(
tickformat=',.0%',
)
fig.show()
you need to use marker_colors to have individual colors. You can define a list with the colors you need and assign it to `marker_colors1. You can set them to whatever you need. Here is the updated code...
import plotly.graph_objects as go
tensions = {'Supportive': 39, 'Neutral': 27, 'Resistant': 34}
items = tensions.items()
x = [item[0] for item in items]
y = [item[1] for item in items]
colors = ['green', 'yellow', 'red']
fig = go.Figure()
fig.add_trace(go.Bar(x=x,y=y,width=0.2,marker_color=colors))
fig.update_layout(
template='simple_white',
paper_bgcolor='#F9F9FA',
plot_bgcolor='#F9F9FA',
height=200,
margin=dict(t=20, b=20, l=60, r=40),)
fig.update_yaxes(tickformat=',.0%',)
Output plot

How to set properties on a row/column in a grid of plotly plots?

Suppose I'm plotting 2 charts on each row, 10 rows, using plotly:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
N=10
fig = make_subplots(rows=N, cols=2)
fig.add_trace(
go.Scatter(x=x, y=y),
row=1, col=1
)
fig.add_trace(
go.Candlestick(
x=df_kline.index,
open=df_kline['O'],
high=df_kline['H'],
low=df_kline['L'],
close=df_kline['C']
),
row=1, col=2
)
:
fig.show()
How can I set a yaxis_title for each row?
How can I set the y-axis range to be [1,10] for the entire first column, and only show the ticklabels at the bottom of the plot?
I hope this qualifies as a single question rather than two, as it's dealing with group-by-row / group-by-col.
FOOTNOTE:
Following from the comments in the accepted answer, one can set settings on multiple subplots thus:
subplot_settings = {
'rangeslider_visible': True,
'rangeslider_thickness': 0.05
}
kwargs = {
f'xaxis{k}' : subplot_settings
for k in range(2, 2*N, 2)
}
fig.update_layout(**kwargs)
(Untested)
Since no data was presented, I responded to the challenge with four subplots using a certain stock price; the title and range of the y-axis for each row in the first one can be set in the y-axis settings. Also, in the settings section of the subplot, if you set the shared axis to x-axis, only the bottom x-axis will be available.
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np
import pandas as pd
x = np.linspace(0,1, 100)
y = np.cumsum(x)
import yfinance as yf
df_kline = yf.download("AAPL", start="2021-01-01", end="2021-03-01")
df_kline.rename(columns={'Open':'O','High':'H','Low':'L','Close':'C'}, inplace=True)
N=2
fig = make_subplots(rows=N, cols=2,
shared_xaxes=True, )# vertical_spacing=0.1
fig.add_trace(
go.Scatter(x=x, y=y),
row=1, col=1
)
fig.add_trace(
go.Candlestick(
x=df_kline.index,
open=df_kline['O'],
high=df_kline['H'],
low=df_kline['L'],
close=df_kline['C'],
),
row=1, col=2,
)
fig.add_trace(
go.Scatter(x=x, y=y),
row=2, col=1
)
fig.add_trace(
go.Candlestick(
x=df_kline.index,
open=df_kline['O'],
high=df_kline['H'],
low=df_kline['L'],
close=df_kline['C'],
),
row=2, col=2
)
fig.update_layout(autosize=False, height=600, width=1000, showlegend=False)
# rangeslider visible false
fig.update_layout(title='Custome subplots',
xaxis2=dict(rangeslider=dict(visible=False)),
xaxis4=dict(rangeslider=dict(visible=False)))
# yxais customize
fig.update_layout(yaxis1=dict(range=[0,10], title='test'),
yaxis3=dict(range=[0,10], title='test2'))
fig.show()

Convert plotly marker from continuous to discrete

Following is my input file i'm trying to display on a map using plotly.
data.csv
lat,long,type
-7.80715,110.371203,1
-7.791087,110.368346,3
-7.778744,110.365107,7
-7.77877,110.365379,4
The script works but the scale is displayed in a continuous format. I tried to convert the column type to text as mentioned here but I couldn't get it to work. Is there a easier way to fix this problem?
df = pd.read_csv("data.csv").dropna()
fig = go.Figure(go.Scattermapbox(
lat=df["lat"].tolist(),
lon=df["long"].tolist(),
mode='markers',
text=df['type'].tolist(),
marker=go.scattermapbox.Marker(
size=10,
color=df['type'],
showscale=True
),
))
fig.show()
If you want to specify a discrete color, you can either deal with it directly as a list of color specifications, or you can specify the default color name in plotly_express.
import plotly.graph_objects as go
import plotly.express as px
mapbox_access_token = open("mapbox_api_key.txt").read()
colors = px.colors.qualitative.D3
fig = go.Figure(go.Scattermapbox(
lat=df["lat"].tolist(),
lon=df["long"].tolist(),
mode='markers',
text=df['type'].tolist(),
marker=go.scattermapbox.Marker(
size=10,
color=colors,
showscale=False
),
))
fig.update_layout(
autosize=False,
height=450,
width=1000,
mapbox=dict(
accesstoken=mapbox_access_token,
style="outdoors",
center=dict(
lat=-7.78,
lon=110.365
),
zoom=10),
showlegend = False
)
fig.show()

Plot.ly draw reference lines on subplot?

I wrote the function below to make a vertical reference line on a figure.
from plotly import graph_objects as go
import plotly.express as px
def add_vline(fig, x=0, text=None):
if text is None:
text = str(x)
fig.update_layout(
shapes=list(fig.layout.shapes) + [
go.layout.Shape(
type="line",
x0=x,
x1=x,
yref="paper",
y0=0,
y1=1,
line=dict(
color="Red",
width=2
)
)
],
annotations=list(fig.layout.annotations) + [
go.layout.Annotation(
x=x,
y=0.5,
yref="paper",
text=text
)
]
)
gapminder = px.data.gapminder()
for continent in gapminder.continent.unique():
fig = px.histogram(gapminder, x="lifeExp", title=f'Life expectancy in {continent}')
add_vline(fig, gapminder[gapminder.continent == continent].lifeExp.median())
# add_figure_to_subplot() ?
I can view these individually, but I'd like to make a report with all these generated figures shown in order. How can I either make a subplot of these figure objects, or replicate these plots within subplot traces?

Categories