Plot.ly draw reference lines on subplot? - python

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?

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()

Setting boundaries for datetime x axis on Plotly (Python)

I have to plot some chronologically-ordered values (one value per month, in my case) on a Plotly (Python) graph. Also, I have to add a "end of period label" (i.e. a marker with text indicating the last value of the series) that has to be positioned at 'middle right'.
A working example would be something like this:
import pandas as pd
import numpy as np
import plotly.graph_objects as go
date_range = pd.to_datetime(pd.date_range(start='1/1/2013', end='9/1/2022', freq='M').tolist()).date
values = np.random.randint(100, size=len(date_range)).tolist()
fig = go.Figure(
)
fig.add_trace(go.Scatter(
showlegend=False,
x=date_range,
y=values,
mode='lines',
line=dict(
width=2,
color="red",
)
)
)
fig.add_trace(go.Scatter(
showlegend=False,
x=[date_range[-1]],
y=[values[-1]],
text=[values[-1]],
textposition='middle right',
texttemplate="%{text:.3f}",
mode='markers+text',
line=dict(
width=2,
color="red",
)
)
)
fig.update_layout(
xaxis=dict(
tickformat="%m\n<b>%Y", dtick="M3",
)
)
which produces the following plot:
I am facing the following problem: the end of period label "extends" beyond the last value of the date range and makes the x axis go into the green area, which are all undesired months (for example, those that extend beyond the last value of the date range and into 2023).
I tried several things to "erase" or delete that undesired part of the x axis, but nothing worked properly: either the end of period label was cut in half or the whole x axis disappeared.
Thank you in advance for any help or suggestion.
as per #r0beginners comments
given text is outside graph area use an annotation for the text
make marker scatter just mode=markers
explicitly state xaxis range range=date_range[[0,-1]]
import pandas as pd
import numpy as np
import plotly.graph_objects as go
date_range = pd.to_datetime(
pd.date_range(start="1/1/2013", end="9/1/2022", freq="M").tolist()
).date
values = np.random.randint(100, size=len(date_range)).tolist()
fig = go.Figure()
fig.add_trace(
go.Scatter(
showlegend=False,
x=date_range,
y=values,
mode="lines",
line=dict(
width=2,
color="red",
),
)
)
fig.add_trace(go.Scatter(
showlegend=False,
x=[date_range[-1]],
y=[values[-1]],
mode='markers',
marker_size=15
)
)
fig.add_annotation(
x = date_range[-1],
y = values[-1],
text = values[-1],
xshift=10,
yshift=0,
showarrow=False
)
fig.update_layout(
xaxis=dict(
tickformat="%m\n<b>%Y",
dtick="M3",
range=date_range[[0,-1]]
)
)

How to add an extra point over a boxplot graph with plotly?

I am trying to overlay a point over a boxplot with Plotly and Python. I am able to add two traces to the same graph, but I couldn't find a way to make the extra point closer to the boxplot.
This is the image I get:
and the code that generates it is:
x = np.fromiter(duplicates.values(), dtype=float)
fig = go.Figure()
fig.update_layout(autosize=False, width=400, height=150, paper_bgcolor="White", plot_bgcolor='rgba(0,0,0,0)',
hovermode=False, margin=dict(l=10, r=10, b=10, t=10, pad=4),
boxmode='group', boxgroupgap=0.25,
boxgap=0.25,
)
fig.add_trace(go.Box(x=x, showlegend=False))
fig.add_trace(go.Scatter(x=np.array(duplicates[sample_id]), y=np.array(0), mode='markers', showlegend=False))
fig.update_xaxes(title='')
fig.update_yaxes(showticklabels=False)
my_div = plotly.offline.plot(fig, output_type='div',
show_link=False,
config=dict(
displayModeBar=False
))

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()

Hi-Low lines in Plotly Line Chart

I am trying to replicate this excel line chart in python using plotly.
Is there any way to add the high-low lines between the two line graphs in Plotly?
Thanks
Just an update on this post. Plotly doesn't seem to have a property to draw lines between points of 2 line plots. So I made the connecting lines as an array of trace and then plotted them on the same figure. Here's a snapshot of resulting plot
:
trace_1 = go.Scatter(x=x_arr, y=y1_arr, name='plot1', line=dict(color = ('royalblue')), mode='lines+markers')
trace_2 = go.Scatter(x=x_arr, y=y2_arr, name='plot2', line=dict(color = ('orange')), mode='lines+markers')
layout_1 = go.Layout(
height=420,
width=800,
title=go.layout.Title(
text='title',
),
xaxis=go.layout.XAxis(
title='x axis',
),
yaxis=go.layout.YAxis(
title='y axis',
)
)
data = []
trace_3_arr = np.array([])
for i in range(0, len(x_arr)):
trace_i = go.Scatter(x=[x_arr[i], x_arr[i]], y=[y1_arr[i], y2_arr[i]], line=dict(color = ('black'), width=1), showlegend=False)
trace_3_arr = np.append(trace_3_arr, trace_i)
data.append(trace_i)
data.append(trace_1)
data.append(trace_2)
fig = go.Figure(data=data, layout=layout_1)
plot(fig)

Categories