Plotly: How to show subplot titles at the bottom - python

Given this example from plotly documentation
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(
rows=2, cols=2,
specs=[[{}, {}],
[{"colspan": 2}, None]],
subplot_titles=("First Subplot","Second Subplot", "Third Subplot"))
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=2)
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 1, 2]),
row=2, col=1)
fig.update_layout(showlegend=False, title_text="Specs with Subplot Title")
fig.show()
Which is displayed as
How to change it so the subtitle is shown at the bottom?

As far as I know, there is no direct setting, so you can check the actual annotation position in fig.layout and adjust it.
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(
rows=2, cols=2,
specs=[[{}, {}],
[{"colspan": 2}, None]],
subplot_titles=("First Subplot","Second Subplot", "Third Subplot"))
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=1)
fig.add_trace(go.Scatter(x=[1, 2], y=[1, 2]),
row=1, col=2)
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[2, 1, 2]),
row=2, col=1)
fig.update_layout(showlegend=False, title_text="Specs with Subplot Title")
fig.layout.annotations[0].update(y=0.40)
fig.layout.annotations[1].update(y=0.40)
fig.layout.annotations[2].update(y=-0.2)
fig.show()
fig.layout
Layout({
'annotations': [{'font': {'size': 16},
'showarrow': False,
'text': 'First Subplot',
'x': 0.225,
'xanchor': 'center',
'xref': 'paper',
'y': 1.0,
'yanchor': 'bottom',
'yref': 'paper'},
{'font': {'size': 16},
'showarrow': False,
'text': 'Second Subplot',
'x': 0.775,
'xanchor': 'center',
'xref': 'paper',
'y': 1.0,
'yanchor': 'bottom',
'yref': 'paper'},
{'font': {'size': 16},
'showarrow': False,
'text': 'Third Subplot',
'x': 0.5,
'xanchor': 'center',
'xref': 'paper',
'y': 0.375,
'yanchor': 'bottom',
'yref': 'paper'}],
'showlegend': False,
'template': '...',
'title': {'text': 'Specs with Subplot Title'},
'xaxis': {'anchor': 'y', 'domain': [0.0, 0.45]},
'xaxis2': {'anchor': 'y2', 'domain': [0.55, 1.0]},
'xaxis3': {'anchor': 'y3', 'domain': [0.0, 1.0]},
'yaxis': {'anchor': 'x', 'domain': [0.625, 1.0]},
'yaxis2': {'anchor': 'x2', 'domain': [0.625, 1.0]},
'yaxis3': {'anchor': 'x3', 'domain': [0.0, 0.375]}
})

Related

Add multiple` plotly.express.bar` figures into one window

I have 3 bar charts with separated data-frames and x,y labels. I can not use make_subplot tool since it is compatible with graph_object instance, not with express.bar. In this case, I've read documentations about facet_row(facet_col) properties which plots bars in one figure but it does not fit to my case. I literally want 3 different figures in one page/window.
I create bar charts as below:
import plotly.express as px
x = ['one', 'two', 'three']
y = [1, 2, 3]
dataframe1 = {
"x_axis_1": x,
"y_axis_1": y
}
fig1 = px.bar(dataframe1, x="x_axis_1", y="y_axis_1")
fig1.update_xaxes(type='category')
Thank you for any idea in advance!
As you mentioned the add_traces expects us to input instances of trace classes from the plotly.graph_objects package (e.g plotly.graph_objects.Scatter, plotly.graph_objects.Bar) (see here)
However since you do not want to use graph_objects we have to find a workaround
Each fig that you create using plotly express has 2 parts : data and layout
For example for your bar chart, if I do:
print (fig1)
>>>
Figure({
'data': [{'alignmentgroup': 'True',
'hovertemplate': 'x_axis_1=%{x}<br>y_axis_1=%{y}<extra></extra>',
'legendgroup': '',
'marker': {'color': '#636efa'},
'name': '',
'offsetgroup': '',
'orientation': 'v',
'showlegend': False,
'textposition': 'auto',
'type': 'bar',
'x': array(['one', 'two', 'three'], dtype=object),
'xaxis': 'x',
'y': array([1, 2, 3], dtype=int64),
'yaxis': 'y'}],
'layout': {'barmode': 'relative',
'legend': {'tracegroupgap': 0},
'margin': {'t': 60},
'template': '...',
'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': 'x_axis_1'}},
'yaxis': {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'y_axis_1'}}}
})
If we check the data parameter its a list of plotly graph_object classes:
print (fig1['data'][0])
>>>
Bar({
'alignmentgroup': 'True',
'hovertemplate': 'x_axis_1=%{x}<br>y_axis_1=%{y}<extra></extra>',
'legendgroup': '',
'marker': {'color': '#636efa'},
'name': '',
'offsetgroup': '',
'orientation': 'v',
'showlegend': False,
'textposition': 'auto',
'x': array(['one', 'two', 'three'], dtype=object),
'xaxis': 'x',
'y': array([1, 2, 3], dtype=int64),
'yaxis': 'y'
})
print(type(fig1['data'][0]))
>>>
<class 'plotly.graph_objs._bar.Bar'>
So basically we have to extract this out from the plotly express figure and pass it to add_traces for it to work
The complete solution
Generate some data:
x1 = ['one', 'two', 'three']
y1 = [1, 2, 3]
x2 = ['five', 'six', 'seven']
y2 = [5, 6, 7]
x3 = ['eight', 'nine', 'ten']
y3 = [8, 9, 10]
dataframe1 = {
"x_axis_1": x,
"y_axis_1": y
}
dataframe2 = {
"x_axis_2": x2,
"y_axis_2": y2
}
dataframe3 = {
"x_axis_3": x3,
"y_axis_3": y3
}
Generate the plot:
from plotly.subplots import make_subplots
fig = make_subplots(rows=3, cols=1)
fig1 = px.bar(dataframe1, x="x_axis_1", y="y_axis_1")
fig2 = px.bar(dataframe2, x="x_axis_2", y="y_axis_2")
fig3 = px.bar(dataframe3, x="x_axis_3", y="y_axis_3")
fig.add_trace(fig1['data'][0], row=1, col=1)
fig.add_trace(fig2['data'][0], row=2, col=1)
fig.add_trace(fig3['data'][0], row=3, col=1)
fig.show()
Output:
As you can see by querying the data key from the plotly express figure, we get the required format we need to pass to the add_traces method.

Is it possible to reverse bullet charts in plotly?

I created a bullet chart with a negative and positive dimension in plotly.go. However, when plotting my bar it always starts from -1. Is there a way to set the starting point at zero, so it can align in both dimensions from there?
Reproducable example:
act = 0.123
avg = 0.13
before = 0.15
fig = go.Figure(go.Indicator(
mode="number+gauge+delta", value=act,
domain={'x': [0.1, 1], 'y': [0, 1]},
title={'text': "<b>S-Score</b>"},
delta={'reference': before},
gauge={
'shape': "bullet",
'tick0':0,
'axis': {'range': [-1, 1]},
'threshold': {
'line': {'color': "white", 'width': 2},
'thickness': 0.75, 'value': avg},
'steps': [
{'range': [-1, 0], 'color': "#ff6666"},
{'range': [0, 1], 'color': "#89ac76"}
],
'bar': {'color': "grey"}}))
Actual Output:
Output I want:
I've done a lot of research and haven't found a solution. I propose a trick approach and a proposal to change the x-axis. This is a bit far from the answer you expect.
import plotly.graph_objects as go
act = 0.123
avg = 0.13
before = 0.15
fig = go.Figure(go.Indicator(
mode = "number+gauge+delta", value = act,
domain = {'x': [0.1, 1], 'y': [0, 1]},
title = {'text' :"<b>S-Score</b>"},
delta = {'reference': before},
gauge = {
'shape': "bullet",
'axis': {'range': [-1, 1]},
'threshold': {
'line': {'color': "white", 'width': 2},
'thickness': 0.75,
'value': avg},
'steps': [
{'range': [-1, 0], 'color': "#ff6666"},
{'range': [0, 1], 'color': "#89ac76"}],
'bar': {'color':'#ff6666'}
}))
fig.update_layout(height = 250)
fig.show()
import plotly.graph_objects as go
act = 0.123
avg = 0.13
before = 0.15
fig = go.Figure(go.Indicator(
mode = "number+gauge+delta", value = act,
domain = {'x': [0.1, 1], 'y': [0, 1]},
title = {'text' :"<b>S-Score</b>"},
delta = {'reference': before},
gauge = {
'shape': "bullet",
'axis': {'range': [0, 1]},
'threshold': {
'line': {'color': "white", 'width': 2},
'thickness': 0.75,
'value': avg},
'steps': [
{'range': [-1, 0], 'color': "#ff6666"},
{'range': [0, 1], 'color': "#89ac76"}],
'bar': {'color':'grey',
'line': {'color':'#444', 'width':2},
}}))
fig.update_layout(height = 250)
fig.show()

Animated plot with `plotly`

I'd like to plot a convergence process of the MLE algorithm with the plotly library.
Requirements:
the points have to be colored colored in the colors of the clusters, and change accordingly each iteration
the centroids of the clusters should be plotted on each iteration.
A plot of a single iteration may be produced by Code 1, with the desired output shown in Figure 1:
Code 1
import plotly.graph_objects as go
import numpy as np
A = np.random.randn(30).reshape((15, 2))
centroids = np.random.randint(10, size=10).reshape((5, 2))
clusters = [1, 2, 3, 4, 5]
colors = ['red', 'green', 'blue', 'yellow', 'magenta']
fig = go.Figure()
for i in range(5):
fig.add_trace(
go.Scatter(
x=A[i:i+3][:, 0],
y=A[i:i+3][:, 1],
mode='markers',
name=f'cluster {i+1}',
marker_color=colors[i]
)
)
for c in clusters:
fig.add_trace(
go.Scatter(
x=[centroids[c-1][0]],
y=[centroids[c-1][1]],
name=f'centroid of cluster {c}',
mode='markers',
marker_color=colors[c-1],
marker_symbol='x'
)
)
fig.show()
Figure 1
I've seen this tutorial, but it seems that you can plot only a single trace in a graph_objects.Frame(), and Code 2 represents a simple example for producing an animated scatter plot of all the points, where each frame plots points from different cluster and the centroids:
Code 2
import plotly.graph_objects as go
import numpy as np
A = np.random.randn(30).reshape((15, 2))
centroids = np.random.randint(10, size=10).reshape((5, 2))
clusters = [1, 2, 3, 4, 5]
colors = ['red', 'green', 'blue', 'yellow', 'magenta']
fig = go.Figure(
data=[go.Scatter(x=A[:3][:,0], y=A[:3][:,1], mode='markers', name='cluster 1', marker_color=colors[0])],
layout=go.Layout(
xaxis=dict(range=[-10, 10], autorange=False),
yaxis=dict(range=[-10, 10], autorange=False),
title="Start Title",
updatemenus=[dict(
type="buttons",
buttons=[dict(label="Play",
method="animate",
args=[None])])]
),
frames=[go.Frame(data=[go.Scatter(x=A[:3][:,0], y=A[:3][:,1], mode='markers', name='cluster 2', marker_color=colors[1])]),
go.Frame(data=[go.Scatter(x=A[3:5][:,0], y=A[3:5][:,1], mode='markers', name='cluster 3', marker_color=colors[2])]),
go.Frame(data=[go.Scatter(x=A[5:8][:,0], y=A[5:8][:,1], mode='markers', name='cluster 4', marker_color=colors[3])]),
go.Frame(data=[go.Scatter(x=A[8:][:,0], y=A[8:][:,1], mode='markers', name='cluster 5', marker_color=colors[4])]),
go.Frame(data=[go.Scatter(x=[centroids[0][0]], y=[centroids[0][1]], mode='markers', name='centroid of cluster 1', marker_color=colors[0], marker_symbol='x')]),
go.Frame(data=[go.Scatter(x=[centroids[1][0]], y=[centroids[1][1]], mode='markers', name='centroid of cluster 2', marker_color=colors[1], marker_symbol='x')]),
go.Frame(data=[go.Scatter(x=[centroids[2][0]], y=[centroids[2][1]], mode='markers', name='centroid of cluster 3', marker_color=colors[2], marker_symbol='x')]),
go.Frame(data=[go.Scatter(x=[centroids[3][0]], y=[centroids[3][1]], mode='markers', name='centroid of cluster 4', marker_color=colors[3], marker_symbol='x')]),
go.Frame(data=[go.Scatter(x=[centroids[4][0]], y=[centroids[4][1]], mode='markers', name='centroid of cluster 5', marker_color=colors[4], marker_symbol='x')])]
)
fig.show()
Why does Code 2 does not fit my needs:
I need to plot all the frames produced by Code 2 in a single frame each iteration of the algorithm (i.e. each frame of the desired solution will look like Figure 1)
What I have tried:
I have tried producing a graph_objects.Figure(), and adding it to a graph_objects.Frame() as shown in Code 3, but have gotten Error 1.
Code 3:
import plotly.graph_objects as go
import numpy as np
A = np.random.randn(30).reshape((15, 2))
centroids = np.random.randint(10, size=10).reshape((5, 2))
clusters = [1, 2, 3, 4, 5]
colors = ['red', 'green', 'blue', 'yellow', 'magenta']
fig = go.Figure()
for i in range(5):
fig.add_trace(
go.Scatter(
x=A[i:i+3][:, 0],
y=A[i:i+3][:, 1],
mode='markers',
name=f'cluster {i+1}',
marker_color=colors[i]
)
)
for c in clusters:
fig.add_trace(
go.Scatter(
x=[centroids[c-1][0]],
y=[centroids[c-1][1]],
name=f'centroid of cluster {c}',
mode='markers',
marker_color=colors[c-1],
marker_symbol='x'
)
)
animated_fig = go.Figure(
data=[go.Scatter(x=A[:3][:, 0], y=A[:3][:, 1], mode='markers', name=f'cluster 0', marker_color=colors[0])],
layout=go.Layout(
xaxis=dict(range=[-10, 10], autorange=False),
yaxis=dict(range=[-10, 10], autorange=False),
title="Start Title",
updatemenus=[dict(
type="buttons",
buttons=[dict(label="Play",
method="animate",
args=[None])])]
),
frames=[go.Frame(data=[fig])]
)
animated_fig.show()
Error 1:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-681-11264f38e6f7> in <module>
43 args=[None])])]
44 ),
---> 45 frames=[go.Frame(data=[fig])]
46 )
47
~\Anaconda3\lib\site-packages\plotly\graph_objs\_frame.py in __init__(self, arg, baseframe, data, group, layout, name, traces, **kwargs)
241 _v = data if data is not None else _v
242 if _v is not None:
--> 243 self["data"] = _v
244 _v = arg.pop("group", None)
245 _v = group if group is not None else _v
~\Anaconda3\lib\site-packages\plotly\basedatatypes.py in __setitem__(self, prop, value)
3973 # ### Handle compound array property ###
3974 elif isinstance(validator, (CompoundArrayValidator, BaseDataValidator)):
-> 3975 self._set_array_prop(prop, value)
3976
3977 # ### Handle simple property ###
~\Anaconda3\lib\site-packages\plotly\basedatatypes.py in _set_array_prop(self, prop, val)
4428 # ------------
4429 validator = self._get_validator(prop)
-> 4430 val = validator.validate_coerce(val, skip_invalid=self._skip_invalid)
4431
4432 # Save deep copies of current and new states
~\Anaconda3\lib\site-packages\_plotly_utils\basevalidators.py in validate_coerce(self, v, skip_invalid, _validate)
2671
2672 if invalid_els:
-> 2673 self.raise_invalid_elements(invalid_els)
2674
2675 v = to_scalar_or_list(res)
~\Anaconda3\lib\site-packages\_plotly_utils\basevalidators.py in raise_invalid_elements(self, invalid_els)
298 pname=self.parent_name,
299 invalid=invalid_els[:10],
--> 300 valid_clr_desc=self.description(),
301 )
302 )
ValueError:
Invalid element(s) received for the 'data' property of frame
Invalid elements include: [Figure({
'data': [{'marker': {'color': 'red'},
'mode': 'markers',
'name': 'cluster 1',
'type': 'scatter',
'x': array([-1.30634452, -1.73005459, 0.58746435]),
'y': array([ 0.15388112, 0.47452796, -1.86354483])},
{'marker': {'color': 'green'},
'mode': 'markers',
'name': 'cluster 2',
'type': 'scatter',
'x': array([-1.73005459, 0.58746435, -0.27492892]),
'y': array([ 0.47452796, -1.86354483, -0.20329897])},
{'marker': {'color': 'blue'},
'mode': 'markers',
'name': 'cluster 3',
'type': 'scatter',
'x': array([ 0.58746435, -0.27492892, 0.21002816]),
'y': array([-1.86354483, -0.20329897, 1.99487636])},
{'marker': {'color': 'yellow'},
'mode': 'markers',
'name': 'cluster 4',
'type': 'scatter',
'x': array([-0.27492892, 0.21002816, -0.0148647 ]),
'y': array([-0.20329897, 1.99487636, 0.73484184])},
{'marker': {'color': 'magenta'},
'mode': 'markers',
'name': 'cluster 5',
'type': 'scatter',
'x': array([ 0.21002816, -0.0148647 , 1.13589386]),
'y': array([1.99487636, 0.73484184, 2.08810809])},
{'marker': {'color': 'red', 'symbol': 'x'},
'mode': 'markers',
'name': 'centroid of cluster 1',
'type': 'scatter',
'x': [9],
'y': [6]},
{'marker': {'color': 'green', 'symbol': 'x'},
'mode': 'markers',
'name': 'centroid of cluster 2',
'type': 'scatter',
'x': [0],
'y': [5]},
{'marker': {'color': 'blue', 'symbol': 'x'},
'mode': 'markers',
'name': 'centroid of cluster 3',
'type': 'scatter',
'x': [8],
'y': [6]},
{'marker': {'color': 'yellow', 'symbol': 'x'},
'mode': 'markers',
'name': 'centroid of cluster 4',
'type': 'scatter',
'x': [7],
'y': [1]},
{'marker': {'color': 'magenta', 'symbol': 'x'},
'mode': 'markers',
'name': 'centroid of cluster 5',
'type': 'scatter',
'x': [6],
'y': [2]}],
'layout': {'template': '...'}
})]
The 'data' property is a tuple of trace instances
that may be specified as:
- A list or tuple of trace instances
(e.g. [Scatter(...), Bar(...)])
- A single trace instance
(e.g. Scatter(...), Bar(...), etc.)
- A list or tuple of dicts of string/value properties where:
- The 'type' property specifies the trace type
One of: ['area', 'bar', 'barpolar', 'box',
'candlestick', 'carpet', 'choropleth',
'choroplethmapbox', 'cone', 'contour',
'contourcarpet', 'densitymapbox', 'funnel',
'funnelarea', 'heatmap', 'heatmapgl',
'histogram', 'histogram2d',
'histogram2dcontour', 'image', 'indicator',
'isosurface', 'mesh3d', 'ohlc', 'parcats',
'parcoords', 'pie', 'pointcloud', 'sankey',
'scatter', 'scatter3d', 'scattercarpet',
'scattergeo', 'scattergl', 'scattermapbox',
'scatterpolar', 'scatterpolargl',
'scatterternary', 'splom', 'streamtube',
'sunburst', 'surface', 'table', 'treemap',
'violin', 'volume', 'waterfall']
- All remaining properties are passed to the constructor of
the specified trace type
(e.g. [{'type': 'scatter', ...}, {'type': 'bar, ...}])
I've succeeded to get all the points present in each frame with the use of plotly.express module, as shown in Code 3, but the only thing that is missing there is for the centroids to be marked as xs.
Code 3:
import plotly.express as px
import numpy as np
import pandas as pd
A = np.random.randn(200).reshape((100, 2))
iteration = np.array([1, 2, 3, 4, 5]).repeat(20)
centroids = np.random.randint(10, size=10).reshape((5, 2))
clusters = np.random.randint(1, 6, size=100)
colors = ['red', 'green', 'blue', 'yellow', 'magenta']
df = pd.DataFrame(dict(x1=A[:, 0], x2=A[:, 1], type='point', cluster=pd.Series(clusters, dtype='str'), iteration=iteration))
centroid_df = pd.DataFrame(dict(x1=centroids[:, 0], x2=centroids[:, 1], type='centroid', cluster=[1, 2, 3, 4, 5], iteration=[1, 2, 3, 4, 5]))
df = df.append(centroid_df, ignore_index=True)
px.scatter(df, x="x1", y="x2", animation_frame="iteration", color="cluster", hover_name="cluster", range_x=[-10,10], range_y=[-10,10])
I'd appreciate any help for achieving the desired result. Thanks.
You can add two traces per frame but apparently you need to define these two traces in the first data too. I added again the first two traces as a frame in order to have them visible in subsequent play. Here the full code
import plotly.graph_objects as go
import numpy as np
A = np.random.randn(30).reshape((15, 2))
centroids = np.random.randint(10, size=10).reshape((5, 2))
clusters = [1, 2, 3, 4, 5]
colors = ['red', 'green', 'blue', 'yellow', 'magenta']
fig = go.Figure(
data=[go.Scatter(x=A[:3][:,0],
y=A[:3][:,1],
mode='markers',
name='cluster 1',
marker_color=colors[0]),
go.Scatter(x=[centroids[0][0]],
y=[centroids[0][1]],
mode='markers',
name='centroid of cluster 1',
marker_color=colors[0],
marker_symbol='x')
],
layout=go.Layout(
xaxis=dict(range=[-10, 10], autorange=False),
yaxis=dict(range=[-10, 10], autorange=False),
title="Start Title",
updatemenus=[dict(
type="buttons",
buttons=[dict(label="Play",
method="animate",
args=[None]),
dict(label="Pause",
method="animate",
args=[None,
{"frame": {"duration": 0, "redraw": False},
"mode": "immediate",
"transition": {"duration": 0}}],
)])]
),
frames=[
go.Frame(
data=[go.Scatter(x=A[:3][:,0],
y=A[:3][:,1],
mode='markers',
name='cluster 1',
marker_color=colors[0]),
go.Scatter(x=[centroids[0][0]],
y=[centroids[0][1]],
mode='markers',
name='centroid of cluster 1',
marker_color=colors[0],
marker_symbol='x')
]),
go.Frame(
data=[
go.Scatter(x=A[:3][:,0],
y=A[:3][:,1],
mode='markers',
name='cluster 2',
marker_color=colors[1]),
go.Scatter(x=[centroids[1][0]],
y=[centroids[1][1]],
mode='markers',
name='centroid of cluster 2',
marker_color=colors[1],
marker_symbol='x')
]),
go.Frame(
data=[
go.Scatter(x=A[3:5][:,0],
y=A[3:5][:,1],
mode='markers',
name='cluster 3',
marker_color=colors[2]),
go.Scatter(x=[centroids[2][0]],
y=[centroids[2][1]],
mode='markers',
name='centroid of cluster 3',
marker_color=colors[2],
marker_symbol='x')
]),
go.Frame(
data=[
go.Scatter(x=A[5:8][:,0],
y=A[5:8][:,1],
mode='markers',
name='cluster 4',
marker_color=colors[3]),
go.Scatter(x=[centroids[3][0]],
y=[centroids[3][1]],
mode='markers',
name='centroid of cluster 4',
marker_color=colors[3],
marker_symbol='x')]),
go.Frame(
data=[
go.Scatter(x=A[8:][:,0],
y=A[8:][:,1],
mode='markers',
name='cluster 5',
marker_color=colors[4]),
go.Scatter(x=[centroids[4][0]],
y=[centroids[4][1]],
mode='markers',
name='centroid of cluster 5',
marker_color=colors[4],
marker_symbol='x')
]),
])
fig.show()

Plotly vertical line with legend in python

In plotly website, there is example that can use shape function add vertical or horizontal line in plotly.
import plotly.plotly as py
import plotly.graph_objs as go
trace0 = go.Scatter(
x=[2, 3.5, 6],
y=[1, 1.5, 1],
mode='text',
)
data = [trace0]
layout = {
'xaxis': {
'range': [0, 7]
},
'yaxis': {
'range': [0, 2.5]
},
'shapes': [
# Line Horizontal
{
'type': 'line',
'x0': 2,
'y0': 2,
'x1': 5,
'y1': 2,
'line': {
'color': 'rgb(50, 171, 96)',
'width': 4,
'dash': 'dashdot',
}
}
]
}
fig = {
'data': data,
'layout': layout,
}
py.iplot(fig, filename='shapes-lines')
But I wonder if there is any ways to add legend for the horizontal lines.
I think the only option at the moment is to plot it as a Scatter trace.
For example this snippet of code
import plotly.graph_objects as pgo
fig = pgo.Figure()
fig.add_traces([
pgo.Scatter(
x=[2, 3.5, 6],
y=[1, 1.5, 1],
name='Yet Another Trace'
),
pgo.Scatter(
x=[2,5],
y=[2,2],
line={
'color': 'rgb(50, 171, 96)',
'width': 4,
'dash': 'dashdot',
}, name='Horizontal Line'
)
])
fig.update_layout(**{
'xaxis': {
'range': [0, 7]
},
'yaxis': {
'range': [0, 2.5]
}
})
fig
generates this result:

Increasing opacity of area plot in plotly

How do I increase the opacity or alpha of the 'filled' area of my plot? I tried:
import pandas as pd
import plotly.offline as py
import plotly.graph_objs as go
import cufflinks as cf
from plotly import tools
plotly.offline.init_notebook_mode()
cf.go_offline()
df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
df.iplot(kind='area', fill=True, filename='cuflinks/stacked-area', opacity=.1)
but it doesn't seem to work.
There doesn't seem to be an easy built-in way of achieving this. However, a work-around is to first get the figure object of the plot, modify it to change the opacity, and then plot it.
You can get the figure object using the asFigure attribute like this:
figure = df.iplot(asFigure=True, kind='area', fill=True, filename='cuflinks/stacked-area')
The figure object in this case looks like:
Figure({
'data': [{'fill': 'tonexty',
'fillcolor': 'rgba(255, 153, 51, 0.3)',
'line': {'color': 'rgba(255, 153, 51, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'a',
'text': '',
'type': 'scatter',
'uid': '4dcc1a3e-fba3-4a32-bb2a-40925b4fae5b',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([0.91229144, 0.63049138, 0.22855077, 0.13470399, 0.9114691 , 0.39640368,
0.46534334, 0.20508211, 0.00203548, 0.41343938])},
{'fill': 'tonexty',
'fillcolor': 'rgba(55, 128, 191, 0.3)',
'line': {'color': 'rgba(55, 128, 191, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'b',
'text': '',
'type': 'scatter',
'uid': '1015b30d-7c09-456c-875c-8a211a6ebdeb',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([1.81115175, 1.57534372, 0.41288126, 0.38068805, 1.72268856, 0.87778503,
1.32714727, 0.848242 , 0.51605283, 0.58190402])},
{'fill': 'tonexty',
'fillcolor': 'rgba(50, 171, 96, 0.3)',
'line': {'color': 'rgba(50, 171, 96, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'c',
'text': '',
'type': 'scatter',
'uid': '7d1852ac-b8e7-44e6-ae69-54229d7e2c83',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([2.79222081, 1.58812634, 1.1439478 , 1.30453731, 2.50881795, 1.67681961,
1.85609861, 1.36657712, 0.89024486, 0.82749039])},
{'fill': 'tonexty',
'fillcolor': 'rgba(128, 0, 128, 0.3)',
'line': {'color': 'rgba(128, 0, 128, 1.0)', 'dash': 'solid', 'shape': 'linear', 'width': 1.3},
'mode': 'lines',
'name': 'd',
'text': '',
'type': 'scatter',
'uid': '89b85012-fc95-487c-b7ba-9cb6c249b768',
'x': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64),
'y': array([3.54740551, 1.79856232, 2.1326556 , 2.10560567, 2.64867039, 2.55519564,
2.73888819, 2.23274393, 1.16987343, 1.42794202])}],
'layout': {'legend': {'bgcolor': '#F5F6F9', 'font': {'color': '#4D5663'}},
'paper_bgcolor': '#F5F6F9',
'plot_bgcolor': '#F5F6F9',
'title': {'font': {'color': '#4D5663'}},
'xaxis': {'gridcolor': '#E1E5ED',
'showgrid': True,
'tickfont': {'color': '#4D5663'},
'title': {'font': {'color': '#4D5663'}, 'text': ''},
'zerolinecolor': '#E1E5ED'},
'yaxis': {'gridcolor': '#E1E5ED',
'showgrid': True,
'tickfont': {'color': '#4D5663'},
'title': {'font': {'color': '#4D5663'}, 'text': ''},
'zerolinecolor': '#E1E5ED'}}
})
You'll note that each trace in the data has a fillcolor attribute: 'fillcolor': 'rgba(255, 153, 51, 0.3)'. The last number is the alpha value, which you want to modify. I've made a hacky little function to update the fillcolor attribute of all traces in a figure object:
def update_opacity(figure,opacity):
for trace in range(len(figure['data'])):
# print(figure['data'][trace]['fillcolor'],'-> ',end='')
rgba_split = figure['data'][trace]['fillcolor'].split(',')
figure['data'][trace]['fillcolor'] = ','.join(rgba_split[:-1] + [' {})'.format(opacity)])
# print(figure['data'][trace]['fillcolor'])
return figure
For full opacity, you can do:
figure = update_opacity(figure,1)
Then, simply plot the result with
py.iplot(figure)
Output:

Categories

Resources