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)
Related
I have folder with a lot of csv files. I wanted to search for csv files in certain date range using datepicker feature in plotly and to be able to plot the selected range of files.
files have a naming scheme car1_2020-12-01.csv,
car2_2020-12-07.csv etc.
for some reason i am not able to plot the graph for selected range of dates
from datetime import date
import datetime as datetime
import pandas as pd
from dash import Dash, dcc, html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import glob
from pathlib import Path
app = Dash(__name__)
app.layout = html.Div([
dcc.DatePickerRange(
id='my-date-picker-range',
min_date_allowed=date(2018, 1, 1),
max_date_allowed=date(2025, 1, 1),
initial_visible_month=date(2021, 1, 1),
end_date=date(2021, 1, 2)
),
html.Div([dcc.Graph(id='plot')]),
])
#app.callback(
Output('plot', 'figure'),
Input('my-date-picker-range', 'start_date'),
Input('my-date-picker-range', 'end_date'))
def update_output(start_date, end_date):
path = r'' # use your path
all_files = glob.glob(path + "/*.csv")
print(start_date)
lis = []
for file in all_files:
name,date1 = file.split('_') #file name is split into two parts
date1 = date1.replace('.csv','')
if start_date <= date1 <= end_date: # file date is compared with range
df = pd.read_csv(file, index_col=None, header=0)
lis.append(df)
df = pd.concat(lis, axis=0, ignore_index=True)
fig = make_subplots(specs=[[{"secondary_y":True}]]) # two Y AXIS PLOT IS PLOTTED
fig.add_trace(
go.Scatter(x=df['total_distance'], y=df['fuel'], name="fuel"),
secondary_y=False,
)
fig.add_trace(
go.Scatter(x=df['total_distance'], y=df['Speed'], name="speed"),
secondary_y=True,
)
# Set x-axis title
fig.update_xaxes(title_text="Total distance")
# Set y-axes titles
fig.update_yaxes(title_text="fuel", secondary_y=False)
fig.update_yaxes(title_text="Speed", secondary_y=True)
return (fig)
if __name__ == '__main__':
app.run_server(debug=True)
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)
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.
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')
I'd like to add a polynomial curve to a scatter plot that is rendered using a callback.
Following is my callback function which returns the scatter plot.
#app.callback(Output('price-graph', 'figure'),
[
Input('select', 'value')
]
)
def update_price(sub):
if sub:
fig1 = go.Figure(
data=[go.Scatter(
x=dff['Count'],
y=dff['Rent'],
mode='markers'
)
],
layout=go.Layout(
title='',
xaxis=dict(
tickfont=dict(family='Rockwell', color='crimson', size=14)
),
yaxis=dict(
showticklabels = True
),
)
)
return fig1
Resulting plot:
I am able to add a polyfit line using sklearn.preprocessing.
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
dff = df.groupby(['Rent']).size().reset_index(name='Count')
fig = plt.figure(figsize=(15,8))
x = dff['Count']
y = dff['Rent']
model = make_pipeline(PolynomialFeatures(4), LinearRegression())
model.fit(np.array(x).reshape(-1, 1), y)
x_reg = np.arange(90)
y_reg = model.predict(x_reg.reshape(-1, 1))
plt.scatter(x, y)
plt.plot(x_reg, y_reg)
plt.xlim(0,100)
plt.xlabel('Number of rental units leased')
plt.ylim(10,50)
plt.show()
Is there a way to do this in plotly?
You haven't specified how you're using DASH. In this example I'm using JupyterDASH in JupyterLab (and yes, it's amazing!).
The following plot is produced by the code snippet below. The snippet uses a callback function to change the argument that sets the number of polynomial features nFeatures in:
model = make_pipeline(PolynomialFeatures(nFeatures), LinearRegression())
model.fit(np.array(x).reshape(-1, 1), y)
I'm using a dcc.Slider to change the values.
Default setup with nFeatures = 1
Selected setup using slider with nFeatures = 3
Complete code:
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
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from IPython.core.debugger import set_trace
# Load Data
df = px.data.tips()
# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
html.H1("ScikitLearn: Polynomial features"),
dcc.Graph(id='graph'),
html.Label([
"Set number of features",
dcc.Slider(id='PolyFeat',
min=1,
max=6,
marks={i: '{}'.format(i) for i in range(10)},
value=1,
)
]),
])
# Define callback to update graph
#app.callback(
Output('graph', 'figure'),
[Input("PolyFeat", "value")]
)
def update_figure(nFeatures):
global model
# data
df = px.data.tips()
x=df['total_bill']
y=df['tip']
# model
model = make_pipeline(PolynomialFeatures(nFeatures), LinearRegression())
model.fit(np.array(x).reshape(-1, 1), y)
x_reg = x.values
y_reg = model.predict(x_reg.reshape(-1, 1))
df['model']=y_reg
# figure setup and trace for observations
fig = go.Figure()
fig.add_traces(go.Scatter(x=df['total_bill'], y=df['tip'], mode='markers', name = 'observations'))
# trace for polynomial model
df=df.sort_values(by=['model'])
fig.add_traces(go.Scatter(x=df['total_bill'], y=df['model'], mode='lines', name = 'model'))
# figure layout adjustments
fig.update_layout(yaxis=dict(range=[0,12]))
fig.update_layout(xaxis=dict(range=[0,60]))
print(df['model'].tail())
return(fig)
# Run app and display result inline in the notebook
app.enable_dev_tools(dev_tools_hot_reload =True)
app.run_server(mode='inline', port = 8070, dev_tools_ui=True, #debug=True,
dev_tools_hot_reload =True, threaded=True)