How to remove plot margin in plotly tools.make_subplots? - python

I want to remove the margin of the subplot: tools.make_subplots ( see code plot g01). horizontal_spacing or vertical_spacing does not help.
For a normal plot I can do this with go.Margin(l=0, r=0 ..). (see plot g11 in code).
I just want the same behavior for subplots. Anyone, any Idea?
import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
import base64
from plotly import tools
import plotly.plotly as py
import plotly.graph_objs as go
from collections import deque
import numpy as np
import random
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='g01',),
dcc.Interval(id='graph-update', interval= 1000 * 1),
dcc.Graph(id='g11',),
dcc.Interval(id='graph-update', interval= 1000 * 1),
], style={
'margin-left' : '0',
'margin-right' : '0',
'padding-left' : '0',
'padding-right' : '0',
})
#app.callback(Output('g01', 'figure'),
events=[Event('graph-update', 'interval')])
def update_graph_bar():
trace1 = go.Bar( x=[1, 2, 3], y=[4, 5, 6], showlegend=False)
trace2 = go.Scatter( x=[1, 2, 3], y=[4, 5, 6], showlegend=False)
fig = tools.make_subplots(rows = 1, cols = 2, specs = [[{}, {}]],
horizontal_spacing = 0.00,
vertical_spacing = 0.00,
)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 1, 2)
fig['layout'].update(height=250, width=660,)
return fig
#app.callback(Output('g11', 'figure'),
events=[Event('graph-update', 'interval')])
def update_graph_bar():
data = [
go.Scatter(
x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
y=[0, 1, 2, 3, 4, 5, 6, 7, 8]
)
]
layout = go.Layout(
autosize=False,
width=500,
height=500,
margin=go.Margin(
l=0,
r=0,
b=0,
t=0,
pad=0
),
paper_bgcolor= '#7f7f7f',
plot_bgcolor= '#c7c7c7',
)
fig = go.Figure(data=data, layout=layout)
return fig
IP = '192.168.1.1'
if __name__ == '__main__':
app.run_server(debug=True, host=IP,port= 1111)

Ok found it indirectly in cufflinks wrapper :):
tools_by_cufflink
fig['layout'].update(margin=dict(l=0,r=0,b=0,t=0))

Use this one,I guess this'll fulfill your requirement
fig.update_layout(font_size=16, margin=dict(l=0,r=0,b=0,t=0), mapbox_style =
"open-street-map")

Related

Plotly add border to a specific subplot

So I need to draw a graph with two subplots, and want to add borders to the one above. I am using plotly, but failed to find a way to do so. The borders here are essentially the solid line along the axes, but as a rectangle. Does anyone know how to add borders (axes) to a specific subplot?
My code:
#random generate points#
x1=np.random.normal(50, 10, 1000)
x2=np.random.normal(30, 10, 1000)
x3=np.random.normal(70, 10, 1000)
x1_kde=gaussian_kde(x1)
x1_range=linspace(min(x1), max(x1),len(x1))
x1_evaluated=x1_kde.evaluate(x1_range)
x2_kde=gaussian_kde(x2)
x2_range=linspace(min(x2), max(x2),len(x2))
x2_evaluated=x2_kde.evaluate(x2_range)
x3_kde=gaussian_kde(x3)
x3_range=linspace(min(x3), max(x3),len(x3))
x3_evaluated=x3_kde.evaluate(x3_range)
def bedslistmaker(x,n):
listofbeds = [x] * n
return listofbeds
x1_beds=bedslistmaker('bed 1',len(x1))
x2_beds=bedslistmaker('bed 2',len(x2))
x3_beds=bedslistmaker('bed 3',len(x3))
First three traces for the histogram (KDE)
trace1 = go.Scatter(x=x1_range,y=x1_evaluated,xaxis="x2", yaxis="y2", \
mode='lines',line={'color': '#377e22','width': 1},marker={'color':'#377e22'},\
fill='tozeroy',fillcolor='rgba(55, 126, 34, 0.25)',showlegend=True,name='x1')
trace2 = go.Scatter(x=x2_range,y=x2_evaluated,xaxis="x2", yaxis="y2", \
mode='lines',line={'color': '#0480A6','width': 1},marker={'color':'#0480A6'},\
fill='tozeroy',fillcolor='rgba(4, 128, 166, 0.25)',showlegend=True,name='x2')
trace3 = go.Scatter(x=x3_range,y=x3_evaluated,xaxis="x2", yaxis="y2", \
mode='lines',line={'color': '#FF0000','width': 1},marker={'color':'#FF0000'},\
fill='tozeroy',fillcolor='rgba(255, 0, 0, 0.25)',showlegend=True,name='x3')
Last three for the sticks below
trace4=go.Scatter(x=x1,y=x1_beds,mode="markers",xaxis= "x1", yaxis= "y1",marker={
"color": "#377e22",
"symbol": "line-ns-open"},
text=None,
showlegend=False)
trace5=go.Scatter(x=x2,y=x2_beds,mode="markers",xaxis= "x1", yaxis= "y1",marker={
"color": "#0480A6",
"symbol": "line-ns-open"
}, text=None,showlegend=False)
trace6=go.Scatter(x=x3,y=x3_beds,mode="markers",xaxis= "x1", yaxis= "y1",marker={
"color": "#FF0000",
"symbol": "line-ns-open"
}, text=None,showlegend=False)
data=[trace1,trace2,trace3,trace4,trace5,trace6]
layouts
layout = go.Layout(
xaxis1=go.layout.XAxis(
domain=[0.00, 1],
anchor="x1",
showticklabels=False),
yaxis1=go.layout.YAxis(
domain=[0.01, 0.17],
anchor="y1",
showticklabels=False,
title=go.layout.yaxis.Title(
font=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'))),
yaxis2=go.layout.YAxis(
domain=[0.17, 1],
anchor="y2",
showticklabels=True,
title=go.layout.yaxis.Title(
text='Probability Density',
font=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'))),
)
fig=go.Figure(data=data,layout=layout)
#fig.layout.update(showlegend=False)
fig.layout.update(template='plotly_white')#barmode='overlay'
fig.update_layout(
legend=go.layout.Legend(
x=0.73,
y=0.97,
traceorder="normal",
font=dict(
family="Courier New,monospace",
size=10,
color="#7f7f7f"
),
#bgcolor="white",
bordercolor="black",
borderwidth=1
)
)
fig.update_layout(
margin=dict(l=80, r=80, t=50, b=80))
fig.layout.update(template='plotly_white')#barmode='overlay'
fig.update_layout(autosize=False,width=1000,height=618)
fig.show()
You can set axis lines with so called mirrors for any subplot by referencing their position with row, col like this:
fig.update_xaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
fig.update_yaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
Plot:
Code:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
fig = make_subplots(rows=2, cols=1)
fig.append_trace(go.Scatter(
x=[3, 4, 5],
y=[1000, 1100, 1200],
), row=1, col=1)
fig.append_trace(go.Scatter(
x=[2, 3, 4],
y=[100, 110, 120],
), row=2, col=1)
fig.update_xaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
fig.update_yaxes(showline = True, linecolor = 'black', linewidth = 1, row = 1, col = 1, mirror = True)
fig.update_layout(height=600, width=600, title_text="Border for upper subplot")
f = fig.full_figure_for_development(warn=False)
fig.show()

Dash+Plotly Synchronize zoom and pan between two plots using imshow

I try to synchronize zoom and pan between two graphs in a dashboard (dash + plotly). I obtain strange behavior when I zoom on a graph, the second graph does not update. I need to zoom on the second graph to make both graphs update but not with the same zoom nor the same location on the graphs. Furthermore the shapes of the two graphs change.
Below is the code I am in. I do not see I am doing wrong.
import os
from dash import Dash, html, dcc, Input, Output, State
import plotly.express as px
import numpy as np
import rasterio as rio
app2 = Dash(__name__)
data_folder = r'.\data'
store = {}
for filename in os.listdir(data_folder):
if os.path.isfile(os.path.join(data_folder, filename)):
band_name = filename.replace('.', '_').split(sep='_')[-2]
with rio.open(os.path.join(data_folder, filename)) as dataset:
nb_band = dataset.count
if nb_band == 1:
data = dataset.read(1)
else:
data = dataset.read(tuple(range(1, nb_band + 1)))
if band_name == 'triband':
data = np.swapaxes(data, 2, 0)
data = np.swapaxes(data, 0, 1)
store[band_name] = data.astype(float)
else:
store[f'B{band_name}'] = data.astype(float)
fig1 = px.imshow(store['triband'])
fig1.update_xaxes(showticklabels=False, showgrid=False, zeroline=False)
fig1.update_yaxes(showticklabels=False, showgrid=False, zeroline=False)
fig1.update_layout(
margin=dict(l=0, r=0, t=0, b=0),
plot_bgcolor='rgba(0, 0, 0, 0)',
paper_bgcolor='rgba(0, 0, 0, 0)',
)
# Application structure and content
app2.layout = html.Div(className='main', children=[
html.H1(children='Hello Dash', style={'padding': 10}),
html.Div(children=[
html.Div(children=[
dcc.Graph(
id='graph1',
figure=fig1,
responsive=True
)
], style={'padding': 5, 'flex': 1}),
html.Div(children=[
dcc.Graph(
id='graph2',
figure=fig1,
responsive=True
)
], style={'padding': 5, 'flex': 1})
], style={'display': 'flex', 'flex-direction': 'row'}),
])
#app2.callback(Output('graph2', 'figure'),
Input('graph1', 'relayoutData'),
State('graph2', 'figure'))
def graph_event1(select_data, fig):
if select_data is not None:
try:
fig['layout']['xaxis']['range'] = [select_data['xaxis.range[0]'], select_data['xaxis.range[1]']],
fig['layout']['yaxis']['range'] = [select_data['yaxis.range[0]'], select_data['yaxis.range[1]']]
except KeyError:
pass
return fig
#app2.callback(Output('graph1', 'figure'),
Input('graph2', 'relayoutData'),
State('graph1', 'figure'))
def graph_event2(select_data, fig):
if select_data is not None:
try:
fig['layout']['xaxis']['range'] = [select_data['xaxis.range[0]'], select_data['xaxis.range[1]']],
fig['layout']['yaxis']['range'] = [select_data['yaxis.range[0]'], select_data['yaxis.range[1]']]
except KeyError:
pass
return fig
if __name__ == '__main__':
app2.run_server(debug=True)
I found a solution : rather than creating two graphs, I created a graph with several subplots and force zoom and pan between subplots.
fig = make_subplots(rows=1, cols=3, shared_xaxes=True, shared_yaxes=True)
fig.add_trace(
px.imshow(store['triband']).data[0],
row=1, col=1
)
fig.add_trace(
px.imshow(index_store['NDVI']).data[0],
row=1, col=2
)
fig.add_trace(
px.imshow(np.where(index_store['NDVI'] >= np.median(index_store['NDVI']),
0.8 * np.max(index_store['NDVI']),
0.8 * np.min(index_store['NDVI']))
).data[0],
row=1, col=3
)
fig.update_xaxes(matches='x', showticklabels=False, showgrid=False, zeroline=False)
fig.update_yaxes(matches='y', showticklabels=False, showgrid=False, zeroline=False)

Share all x-axes of a subplot (rows and columns)

I try to share all x-axes of a subplot structure with several columns, but I can't get the solution. With 'share_xaxes=True' only the x-axes of the same row are linked, and I am not able to change the 'xaxis' paramater from the figures in the subplot. Any idea?
In the Plotly documentation you can see that the axes have an attribute called scaleanchor (see https://plot.ly/python/reference/#layout-xaxis-scaleanchor). You can use it to connect as many axes as you like. I tested it out on a simple subplot with 2 rows and 2 columns where all x-axes are connected:
import plotly.plotly as py
import plotly.graph_objs as go
# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
def create_figure():
trace1 = go.Scatter(
x=[1, 2, 3],
y=[2, 3, 4]
)
trace2 = go.Scatter(
x=[1, 2, 3],
y=[5, 5, 5],
xaxis='x2',
yaxis='y2'
)
trace3 = go.Scatter(
x=[1, 2, 3],
y=[600, 700, 800],
xaxis='x3',
yaxis='y3'
)
trace4 = go.Scatter(
x=[1, 2, 3],
y=[7000, 8000, 9000],
xaxis='x4',
yaxis='y4'
)
data = [trace1, trace2, trace3, trace4]
layout = go.Layout(
xaxis=dict(
domain=[0, 0.45],
anchor='y'
),
xaxis2=dict(
domain=[0.55, 1],
anchor='y2',
scaleanchor='x'
),
xaxis3=dict(
domain=[0, 0.45],
anchor='y3',
scaleanchor='x'
),
xaxis4=dict(
domain=[0.55, 1],
anchor='y4',
scaleanchor='x'
),
yaxis=dict(
domain=[0, 0.45],
anchor='x'
),
yaxis2=dict(
domain=[0, 0.45],
anchor='x2'
),
yaxis3=dict(
domain=[0.55, 1],
anchor='x3'
),
yaxis4=dict(
domain=[0.55, 1],
anchor='x4'
)
)
fig = go.Figure(data=data, layout=layout)
return fig
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='example-graph',
figure=create_figure()
)
])
if __name__ == '__main__':
app.run_server(debug=True)
I know this post is old, but maybe this can help someone else:
Just use the option shared_xaxes = 'all' when you create subplots with make_subplots() and all x-axes will be shared.

Plotly legend next to each subplot, Python

After noticing that there was no answer to this question at the moment, I would like to know if anyone has an idea how to:
Have a legends for each subplot.
Group legends by name. (Ex: for different subplots, all have the same two curves but with different values).
Here's my Plotly script:
from plotly import tools
import plotly.plotly as py
import plotly.graph_objs as go
import plotly
nom_plot=[]
trace1 = go.Scatter(x=[1, 2, 3], y=[4, 5, 6],name='1',showlegend=True)
nom_plot.append('GRAPH 1')
trace2 = go.Scatter(x=[20, 30, 40], y=[50, 60, 70],name='2',yaxis='y2')
nom_plot.append('GRAPH 2')
trace3 = go.Scatter(x=[300, 400, 500], y=[600, 700, 800],showlegend=False)
nom_plot.append('GRAPH 3')
trace4 = go.Scatter(x=[4000, 5000, 6000], y=[7000, 8000, 9000])
nom_plot.append('GRAPH 4')
trace5 = go.Scatter(x=[20, 30, 40], y=[50, 60, 70])
nom_plot.append('GRAPH 5')
print(trace1)
fig = tools.make_subplots(rows=4, cols=2, subplot_titles=(nom_plot))
fig.append_trace(trace1, 1, 1)
fig['layout']['xaxis1'].update(title='xaxis 1 title')
fig.append_trace(trace2, 1, 1)
fig.append_trace(trace3, 2, 1)
fig.append_trace(trace4, 2, 2)
fig['layout']['yaxis3'].update(title='yaxis 3 title')
fig.append_trace(trace5, 3, 1)
fig['layout']['yaxis2'].update(
overlaying='y1',
side='right',
anchor='x1',
# domain=[0.15, 1],
range=[2, 6],
# zeroline=False,
showline=True,
showgrid=False,
title='yaxis 3 title'
)
fig['layout'].update(height=1000, width=1000, title='Multiple Subplots' +' with Titles')
plotly.offline.plot(fig, filename='multiple-y-subplots6.html')
This what I obtain (Using Plotly Script above):
And this is what I want (Made by Pygal):
The solution is to create an HTML file that merge sevral charts offline rendered as html files:
import plotly
import plotly.offline as py
import plotly.graph_objs as go
fichier_html_graphs=open("DASHBOARD.html",'w')
fichier_html_graphs.write("<html><head></head><body>"+"\n")
i=0
while 1:
if i<=40:
i=i+1
#______________________________--Plotly--______________________________________
color1 = '#00bfff'
color2 = '#ff4000'
trace1 = go.Bar(
x = ['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [25,100,20,7,38,170,200],
name='Debit',
marker=dict(
color=color1
)
)
trace2 = go.Scatter(
x=['2017-09-25','2017-09-26','2017-09-27','2017-09-28','2017-09-29','2017-09-30','2017-10-01'],
y = [3,50,20,7,38,60,100],
name='Taux',
yaxis='y2'
)
data = [trace1, trace2]
layout = go.Layout(
title= ('Chart Number: '+str(i)),
titlefont=dict(
family='Courier New, monospace',
size=15,
color='#7f7f7f'
),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
yaxis=dict(
title='Bandwidth Mbit/s',
titlefont=dict(
color=color1
),
tickfont=dict(
color=color1
)
),
yaxis2=dict(
title='Ratio %',
overlaying='y',
side='right',
titlefont=dict(
color=color2
),
tickfont=dict(
color=color2
)
)
)
fig = go.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Chart_'+str(i)+'.html',auto_open=False)
fichier_html_graphs.write(" <object data=\""+'Chart_'+str(i)+'.html'+"\" width=\"650\" height=\"500\"></object>"+"\n")
else:
break
fichier_html_graphs.write("</body></html>")
print("CHECK YOUR DASHBOARD.html In the current directory")
Result:
I used two side by side Div elements to emulate Plotly subplot. Doing this way, we have independent legends. However, if we want to share an axis, we should do it manually:
app.layout = html.Div(children=[
html.Div(['YOUR FIRST GRAPH OBJECT'],
style = {'float':'left', 'width':'49%'}) ,
html.Div(['YOUR SECOND GRAPH OBJECT'],
style = {'float':'right', 'width':'49%'})
])

Plotly: How to display charts in Spyder?

Since November 2015, plotly is Open-Source and available for python. https://plot.ly/javascript/open-source-announcement/
When trying to do some plots offline, these work in iPython Notebook (version 4.0.4)
But if I try to run them in Spyder (version 2.3.8), i just get the following output:
<IPython.core.display.HTML object>
<IPython.core.display.HTML object>
There's something wrong in my code or the iPython Terminal of Spyder still doesn't support this?
Here goes the example code (taken from https://www.reddit.com/r/IPython/comments/3tibc8/tip_on_how_to_run_plotly_examples_in_offline_mode/)
from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
from plotly.graph_objs import *
init_notebook_mode()
trace0 = Scatter(
x=[1, 2, 3, 4],
y=[10, 11, 12, 13],
mode='markers',
marker=dict(
size=[40, 60, 80, 100],
)
)
data = [trace0]
layout = Layout(
showlegend=False,
height=600,
width=600,
)
fig = dict( data=data, layout=layout )
iplot(fig)
If you'd like to develop your plotly figures in Spyder, perhaps because of Spyders superb variable explorer, you can easily display a non-interactive image by just running fig.show(). Note that this is for newer versions of plotly where you don't have to worry about iplot and plotly.offline.
And if you'd like display your figure in the browser as a fully interactive version, just run:
import plotly.io as pio
pio.renderers.default='browser'
Now your figure will be displayed in your default browser.
To switch back to producing your figure in Spyder, just run:
import plotly.io as pio
pio.renderers.default='svg'
You can check other options too using pio.renderers?:
Renderers configuration
-----------------------
Default renderer: 'svg'
Available rendere <...> wser', 'firefox', 'chrome', 'chromium', 'iframe',
'iframe_connected', 'sphinx_gallery']
You'll find even more details here under Setting the default renderer
Here's a detailed example
Code:
import plotly.graph_objects as go
import plotly.io as pio
#pio.renderers.default = 'svg'
pio.renderers.default = 'browser'
x = ['Product A', 'Product B', 'Product C']
y = [20, 14, 23]
fig = go.Figure(data=[go.Bar(
x=x, y=y,
text=y,
textposition='auto',
)])
fig.show()
Plot:
System info:
Python 3.7.6
Spyder 3.3.1
Plotly 3.2.0
importing plot instead iplot (and changing the last line from iplot(fig) to plot(fig) resolved the problem, at least in python 3:
from plotly.offline import download_plotlyjs, init_notebook_mode, plot
from plotly.graph_objs import *
init_notebook_mode()
trace0 = Scatter(
x=[1, 2, 3, 4],
y=[10, 11, 12, 13],
mode='markers',
marker=dict(
size=[40, 60, 80, 100],
)
)
data = [trace0]
layout = Layout(
showlegend=False,
height=600,
width=600,
)
fig = dict( data=data, layout=layout )
plot(fig)
But instead you could do the following, which is slightly easier:
import plotly
import plotly.graph_objs
plotly.offline.plot({
"data": [
plotly.graph_objs.Scatter( x=[1, 2, 3, 4],
y=[10, 11, 12, 13], mode='markers',
marker=dict(
size=[40, 60, 80, 100]))],
"layout": plotly.graph_objs.Layout(showlegend=False,
height=600,
width=600,
)
})

Categories