Remove responsive feature with Dash plotly - python

I'm on google colab with MacOS 11.5.2.
Dash version I'm using is 1.21.0
I'm usually write dash code in bigger screen, and now I'm notice this issue when move to smaller screen. Here's a the example :
import plotly.express as px
from jupyter_dash import JupyterDash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
app = JupyterDash(__name__,external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dbc.Row([dbc.Col("Top left"),dbc.Col("Top right")]),
dbc.Row([dbc.Col("Bottom left"),dbc.Col("Bottom right")])
]
)
if __name__ == "__main__":
app.run_server()
And the output is as expected, 2 x 2 grid with each word in respective position.
But when I'm replacing the text with plot, the grid structure changed automatically.
app = JupyterDash(__name__,external_stylesheets=[dbc.themes.BOOTSTRAP])
df = px.data.tips()
fig1 = px.histogram(df,x="tip")
fig2 = px.scatter(df,x="total_bill",y="tip")
fig3 = px.bar(df,x="sex")
fig4 = px.histogram(df,x="total_bill")
app.layout = html.Div([
dbc.Row([dbc.Col(dcc.Graph(figure=fig1,id="Histogram tip")),dbc.Col(dcc.Graph(figure=fig2,id="Scatter plot bill vs tip"))]),
dbc.Row([dbc.Col(dcc.Graph(figure=fig3,id="Barplot gender "),width=3),dbc.Col(dcc.Graph(figure=fig4,id="Histogram bill"),width=9)])
]
)
if __name__ == "__main__":
app.run_server()
Now the first row become stacked vertically instead of horizontally stacked. Here's the screenshot (I zoom out a bit)
But if i really zoom out my browser that far, the displayed layout is correctly appear
I don't understand why the responsive layout feature kicks in this scenario and I want to turn it off so my dashboard appear in 2x2 instead of 3 rows layout.

I finally solve it by using dbc.Container to my app and set fluid=False.

Related

Fixing x_range in plotly express histogram messes up x axis in rug plot

I am creating a histogram using plotly express, and I want to use the argument marginal='rug'. When trying to disable zooming on the x axis by using histogram.update_xaxes(fixedrange=True), this messes up the x range in the rugplot.
Here are the two outputs, one with fixedrange=False and one with fixedrange=True. Note how the points above the bars are off in the second plot.
I would really like to disable the zooming, but have the x axes match between the bars and the points. How do I do this?
For reproducibility, here's the code for this minimal example, you can just copy and run it.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd
import dash_daq as daq
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id="graph"),
html.Label("Make x axis zoomable"),
daq.ToggleSwitch(
id='x_toggle_switch',
value=False
)
])
#app.callback(
Output("graph", "figure"),
[Input('x_toggle_switch', 'value')])
def make_x_zoomable(x_zoomable):
start, end = 0, 25
df = pd.DataFrame({'x': [0, 5, 10, 15, 20, 25]})
histogram = px.histogram(df, x='x',
nbins=end - start + 1,
range_x=[start, end],
marginal='rug',
barmode='overlay',
template='plotly_white')
histogram.update_layout(showlegend=False, yaxis_title='y', xaxis_title='x')
# disable zooming
histogram.update_xaxes(fixedrange=x_zoomable)
histogram.update_yaxes(fixedrange=True)
return histogram
app.run_server(debug=True)

Display only single line on hover, hide all other lines

Is there is a way to hide all other lines on a figure, when I am hovering a single one?
Example:
import numpy as np
import plotly.express as px
np.random.seed(42)
data = np.random.randint(0, 10, (5, 10))
fig = px.line(data_frame=pd.DataFrame(data))
fig.show()
will produce:
and I want this, when I hover particular line (but without manually switching off all other lines and keeping X, Y axes dims):
UPD: inside jupyter notebook
The following suggestion draws from the posts Plotly Dash: How to reset the "n_clicks" attribute of a dash-html.button? and Plotly-Dash: How to code interactive callbacks for hover functions in plotly dash and will let you display a single trace by hovering on any point or part of the line. The rest of the traces aren't completely hidden though, but are made grey and transparent in the background so that you can more easily make another selection.
To reset the figure and make all traces fully visible at the same time, just click Clear Selection. I understand that you would prefer a "plain" Jupyter approach to obtain this functionality, but you'd be missing out on the true power of plotly which reveals itself to the full extent only through Dash and JupyterDash. With this suggestion, you won't see any difference between Dash and "plain" Jupyter since the figure, or app, is displayed inline with app.run_server(mode='inline')
Plot 1 - Upon launch. Or after clicking Clear selection
Plot 2 - Selection = trace a
Plot 3 - Selection = trace b
Complete code
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
# pandas and plotly settings
pd.options.plotting.backend = "plotly"
# app info
app = JupyterDash(__name__)
# sample data and figure setup
df = pd.DataFrame(np.random.randint(-1,2,size=(200, 12)), columns=list('abcdefghijkl'))
df = df.cumsum()#.reset_index()
fig = df.plot(title = 'Selected traces = all', template='plotly_dark')#.update_traces(line_color = 'rgba(50,50,50,0.5)')
set_fig = go.Figure(fig)
colors = {d.name:d.line.color for i, d in enumerate(set_fig.data)}
# jupyterdash app
app.layout = html.Div([html.Button('Clear selection', id='clearit', n_clicks=0),
dcc.Graph(id='hoverfig',figure=fig,#clear_on_unhover = True
),])
colors = {d.name:d.line.color for i, d in enumerate(set_fig.data)}
# callbacks
#app.callback(
Output('hoverfig', 'figure'),
[Input('hoverfig', 'hoverData'), Input('clearit', 'n_clicks')])
def display_hover_data(hoverData, resetHover):
changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
if 'clearit' in changed_id:
return set_fig
else:
try:
fig2 = fig.update_layout(title = 'Selected trace = ' + fig.data[hoverData['points'][0]['curveNumber']].name)
fig2.for_each_trace(lambda t: t.update(line_color = 'rgba(50,50,50,0.5)',line_width = 1) if t.name != fig.data[hoverData['points'][0]['curveNumber']].name else t.update(line_color = colors[t.name], line_width = 2))
return fig2
except:
return fig
app.run_server(mode='inline', port = 8070, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)
import plotly.graph_objects as go
import numpy as np
import pandas as pd
# callback function for on_hover
def hide_traces_on_hover(trace, points, selector):
if len(points.point_inds)==1: # identify hover
i = points.trace_index # get the index of the hovered trace
f.data[i].visible = True # keep the hovered trace visible
# create a list of traces you want to hide
hide_traces = [l_trace for idx, l_trace in enumerate(f.data) if idx != i]
for l_trace in hide_traces: # iterate over hide_traces
l_trace.visible = 'legendonly' # hide all remaining traces
# callback function to unhide traces on click
def unhide_traces_on_click(trace, points, selector):
for l_trace in f.data:
l_trace.visible = True
# your sample data frame
np.random.seed(42)
data = np.random.randint(0, 10, (5, 10))
df = pd.DataFrame(data)
f = go.FigureWidget() # create figure widget
f.update_yaxes(autorange=False) # set auto range to false
# define the range of the y-axis using min and max functions
f.update_layout(yaxis_range=[df.values.min()-1, df.values.max()+1])
# create your traces from the data frame
for col in df.columns:
trace = go.Scatter(x=df.index, y=df[col], mode='lines+markers')
f.add_trace(trace)
# assign your functions to each trace
for trace in f.data:
trace.on_hover(hide_traces_on_hover)
trace.on_click(unhide_traces_on_click)
f
If you are running into issues, here is the jupyter notebook support documentation for using FigureWidget and here is the jupyter lab support documentation. Make sure you have the ipywidgets package installed. Also, just as a FYI, here is the FigureWidget documentation.
When you hover over a marker in the graph.
When you click on any marker of the visible trace all the hidden traces will become visible again.

auto ranging y axis in plotly python

I want to plot a graph in plotly. while set the range to zoom with rangelider, the y axis is fixed and make data in flat. I found a page that one expert guy did it, but I can not do it
Is there any one that can make it happen
https://community.plotly.com/t/y-axis-autoscaling-with-x-range-sliders/10245/11
at this page the second graph is a animation gif this is what exactly I have to do
This is the same technique but using dash to capture event and trigger callback. Additional reference: graph slider as input
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.express as px
import numpy as np
import pandas as pd
# generate some data and a figure...
s = 500
df = pd.DataFrame({"date": pd.date_range("1-jan-2020", periods=s), "val": np.random.uniform(0, 1, s)})
df = df.assign(val=df["val"] * (df["date"] - df["date"].min()).dt.days ** 3)
fig = px.line(df, x="date", y="val")
fig = fig.update_layout(xaxis={"rangeslider": {"visible": True}, "range":[df["date"].quantile(.75), df["date"].max()]})
# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
dcc.Graph(id='dashFig', figure=fig),
], style={"font-family": "Arial", "font-size":"0.9em"})
# get callback from rangeslider and update ranges on x & y axis
#app.callback(Output('dashFig', 'figure'),
[Input('dashFig', 'relayoutData')])
def rangesliderchg(relayoutData):
if relayoutData and "xaxis.range" in relayoutData.keys():
s = df.loc[df["date"].between(relayoutData['xaxis.range'][0], relayoutData['xaxis.range'][1]), "val"]
fig["layout"]["yaxis"]["range"] = [s.min(), s.max()]
fig["layout"]["xaxis"]["range"] = relayoutData['xaxis.range']
return fig
# Run app and display result inline in the notebook
app.run_server(mode='inline')

How to graph data from a CSV file using Dash, Plotly

I am new to python and am looking for ways in which I can visualise data. I have come across 'Dash' - but wondered how I would show a graph based on data that is saved in a CSV?
Currently I have this.. But it only shows a blank graph.
Any help would be welcomed - thanks in advance.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import pandas as pd
df = pd.read_csv('d6.csv')
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id="graph"),
html.Button("Switch Axis", id='btn', n_clicks=0)
])
#app.callback(
Output("graph", "figure"),
[Input("btn", "n_clicks")])
def display_graph(n_clicks):
if n_clicks % 2 == 0:
x, y = 'Time', 'R1Temp'
else:
x, y = 'R1Temp', 'Time'
fig = px.line(df, x=x, y=y)
return fig
app.run_server(debug=False)
Pandas is your friend, it gives you access to a data structure called a dataframe. I highly recommend you look through some tutorials on pandas as they come up everywhere in the data science field. In addition plotly often looks for dataframes as inputs into their API.
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html
But to cut to the chase, a dataframe can load a CSV with 100% structure retention
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html#pandas.read_csv
https://datatofish.com/export-dataframe-to-csv/
Once you load the csv to a dataframe you can access rows and columns with queries.
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.columns.html

Animation using plotly

I want to create an animation using plotly library. I need a randomly moving point (from [0,0]) which leaves a trace behing.
Here you can see a video of what I need. - https://imgur.com/a/AgRfNFf
The code snippet below will produce a Plotly Dash app that animates a form of Random Walk. How that walk will appear will depend entirely on what kind of random nunbers you base it on. Here I'm using two accumulated processes for the X and Y axes based on np.random.uniform. But you can easily change that to whatever random process you prefer.
Dash App after 2500 runs
Dash App after 5000 runs
Complete code:
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
# data
np.random.seed(4)
Y = np.random.randint(low=-1, high=2, size=1).tolist()
X = np.random.randint(low=-1, high=2, size=1).tolist()
df = pd.DataFrame({'X':X, 'Y':Y}, columns = ['X', 'Y'])
df.iloc[0]=0
# plotly app
app = JupyterDash(__name__)
app.layout = html.Div([
html.H1("Random stumble"),
dcc.Interval(
id='interval-component',
interval=1*1000, # in milliseconds
),
dcc.Graph(id='graph'),
])
# Define callback to update graph
#app.callback(
Output('graph', 'figure'),
[Input('interval-component', "n_intervals")]
)
def streamFig(value):
global df
Y = np.random.randint(low=-1, high=2, size=1).tolist()
X = np.random.randint(low=-1, high=2, size=1).tolist()
df2 = pd.DataFrame({'X':X, 'Y':Y}, columns = ['X', 'Y'])
df = df.append(df2, ignore_index=True)#.reset_index()
df3=df.copy()
df3=df3.cumsum()
fig = go.Figure(data=go.Scatter(x=df3['X'], y=df3['Y']))
fig.update_layout(title = dict(text = 'x =' + str(X) + ', y ='+str(Y) + ', len = '+str(len(df))))
#fig.update_layout(xaxis=dict(range=[-10,10]))
#fig.update_layout(yaxis=dict(range=[-10,10]))
return(fig)
app.run_server(mode='external', port = 8019, dev_tools_ui=True, debug=True,
dev_tools_hot_reload =True, threaded=False)

Categories