Callback function not upgrading graphs - python

I have a dataset and I want to plot some graphs. I created a plotly graph that loads correctly with a callback function where I can select the year I want the data. The dataset loads correctly and there are no missings or errors. But Whenever I try to change the data nothing happens.
my dataset has columns like this
codass Q NF CURS
240011 1 7 2010
240011 2 5 2010
240012 1 2 2011
I tried starting with a blank graph, and nothing happens. The data is fine cause the initial graph loads correctly it's on the updating procedure.
import pandas as pd
import numpy as np
import dash
import dash_core_components as dcc
from dash.dependencies import Input, Output
import dash_html_components as html
import plotly.graph_objs as go
FaseIni = pd.read_csv('/Users/Jordi/Documents/Universitat/TFG/tfg/Spyder path/qfaseini18.csv',sep=';',encoding='utf-8')
Q=[1,2]
anys=FaseIni['CURS'].unique()
pv = FaseIni.pivot_table( index=['CODASS'], columns=['Q'], values=['NF'], fill_value=0)
trace1=go.Bar(x=pv.index, y =pv[('NF',1)],name='q1')
trace2=go.Bar(x=pv.index, y =pv[('NF',2)],name='q2')
app = dash.Dash()
app.layout = html.Div([
html.Div([
dcc.Dropdown(
id='Anys',
options= [{'label':'2010' , 'value':2010 },{'label':'2011' , 'value':2011 }],
value =2010,
)
]),
html.Div([
dcc.Graph(
id='notes',
figure={
'data':[trace1,trace2]
}
)
])
])
#app.callback(
Output('notes','figure'),
[Input('Anys','value')])
def update_graph(Anys):
pv2 = FaseIni.loc[FaseIni['CURS'] == Anys]
pv2 = pv2.pivot_table( index=['CODASS'], columns=['Q'], values=['NF'],
fill_value=0)
trace3=go.Bar(x=pv2.index, y =pv2[('Anys',1)],name='q1')
trace4=go.Bar(x=pv2.index, y =pv2[('Anys',2)],name='q2')
return {'data':[trace3,trace4]}
The initial graph loads correctly, it just doesn't update

I had this problem the other day. I'm not sure if this will troubleshoot it because I don't have the csv file to test it but try changing to this:
trace3=go.Bar(x=pv2.index, y =pv2[(value,1)],name='q1')
trace4=go.Bar(x=pv2.index, y =pv2[(value,2)],name='q2')

Related

Dynamic update open-street-map position mark in plotly.graph_objects in python ( dash )

In the dash application, I have a map displayed with the center in my position and on it I have a point (mark) in the center again as my position. However, I need to dynamically change my position on the map.
The map itself changes its center without problems, but the point (marker) does not, as if it is anchored in its original position and does not move to a new position (the new center of the map).
Here is a simple code that shows it nicely. After running it, the map is redrawn every 2 seconds as I want. But the point remains in the last-origial position..... Does anyone know what I'm doing wrong?
import random
import dash
from dash import dcc,html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
def get_fig():
# random position as center
lat = 48.8 + 1/random.randrange(300, 800)
lon = 20.1+ 1/random.randrange(300, 800)
fig = go.Figure()
# blue point - should be in center of map , vhy is not ?
fig.add_trace(
go.Scattermapbox(
lat=[lat],
lon=[lon],
mode="markers",
marker=go.scattermapbox.Marker(size=20),
)
)
# open street map with center at lat:lon
fig.update_layout(
height=552,
width=640,
margin={"r": 2, "t": 2, "b": 2, "l": 2},
autosize=True,
mapbox=dict(style="open-street-map", center=dict(lat=lat, lon=lon), zoom=16),
)
return fig
app = dash.Dash()
#app.callback(
Output("graph", "figure"),
Input("my_interval", "n_intervals"))
def update_bar_chart(dummy):
return get_fig()
app.layout = html.Div([
dcc.Graph(id = "graph"),
dcc.Interval(id="my_interval", interval=2000, n_intervals=0, disabled=False),
])
app.run_server(debug=True, use_reloader=False)
I use python 3.9 , plotly version is 5.11.0 and dash version is 2.7.0
I've tried several different ways, but they all fail in the same way.

How To Make Dash DataTables Responsive [Height & Weight] dynamically to fit in any device?

I'm going through the Dash Tables design to create a webpage with data preview, But the problem I'm facing is it's not responsive to browser, Though Column wise it's responsive enough but the height it's not helping at all. I'm using the bellow python code for the same.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
app = Dash(__name__)
df = pd.DataFrame(OrderedDict(
[
[
'Column {}'.format(i + 1), list(range(30))
] for i in range(15)
]
))
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
virtualization=True,
fixed_rows={'headers': True},
style_cell={'minWidth': 95, 'width': 95, 'maxWidth': 95},
style_table={"overflowY":"auto",'maxHeight':'75vh'} # default is 500
)
if __name__ == '__main__':
app.run_server(debug=True)
I'm not getting any proper config to make it responsive height wise. Few ref. doc's I've came across are as follows:
https://dash.plotly.com/datatable/height
https://dash.plotly.com/datatable/style
https://community.plotly.com/t/dash-data-table-not-displayed-on-full-page/68332/14
Adjusting the MaxHeight of a Table in Dash Tables Python
Can someone help here? How can I make this table fully responsive for any screen size ?

I am trying to create a dash app for a Restaurant directory the dropdown filter is work I know but map doesn't update

I have restaurant name, cusines, lat , long as columns. The map I am trying to show on the html page is not updating as per the filter , It shows all the restaurnats.
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
app = dash.Dash('app')
df = pd.read_excel('Resturants.XLSX')
app.layout = html.Div([
html.H1('Resturant map by cusine', style={'text-align': 'center'} ),
dcc.Dropdown(id='cusine_dd',
options=[{'label': i, 'value': i} for i in df.cusines.unique()],
value = 'Chinese',
style={'width':'40%'}),
html.Div(id= 'output', children =[] ),
dcc.Graph(id='mapbycusine', figure={})
])
#app.callback(
[Output(component_id='output', component_property='children'),
Output(component_id='mapbycusine', component_property='figure')],
[Input(component_id='cusine_dd', component_property='value')]
)
def update_figure(input_cusine):
#cusine_filter = 'All'
container = f"Currently showing {input_cusine}"
df_copy = df.copy(deep=True)
if input_cusine:
df_copy = df_copy[df_copy['cusines'] == input_cusine]
print(df_copy.head())
fig = px.scatter_mapbox(data_frame=df_copy, lat='Latitude', lon='Longitude', zoom=3, height=300, hover_data= ['cusines'])
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(height=1000, margin={"r":100,"t":100,"l":100,"b":300})
return container, fig
if __name__ == '__main__':
app.run_server(debug=True)
I am checking every step just to make sure if input and output is working I have used countainers updates on the html page and print the df_copy after filtering data as per the input cusine. The containers give the correct output and the df.copy.head() shows only filltered columns in the console but the map on html dash app is not updating.
I want the map to show the restaurants for just the selected cusine
I cannot reproduce your error, but perhaps some of the steps I took in debugging might prove helpful:
First, I took the first 100 rows of a restaurant dataset from kaggle, and then randomly assigned three different cuisine types to each unique restaurant name. Then when creating the fig object with px.scatter_mapbox, I passed the cuisine column to the color argument and a mapping between cuisine and color to the color_discrete_map argument so that the marker colors will be different when you select different cuisine types from the dropdown.
This is the result, with visible changes between the marker locations as well as the marker colors (depending on the dropdown selection). Also, as you mentioned, the print outs of df_copy from inside your update_figure function match the dropdown selections as expected.
As far as I can tell, the only thing fundamentally different between your dashboard and mine would be the data that was used. Maybe it is possible that you have a bunch of duplicate rows that span multiple cuisines (i.e. imagine I took a data set of only Mexican restaurants, then duplicated all of the rows but switched the cuisine to Italian – then if you select Mexican or Italian from the dropdown, the result would be the same because you're plotting all of the same latitudes and longitudes in each case so the figure wouldn't appear to change, and you might not catch this from examining the df_copy print outs).
Can you verify that your data set doesn't contain duplicate latitude and longitude points with different cuisines assigned to the same point?
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import numpy as np
import pandas as pd
import plotly.express as px
app = dash.Dash('app')
# df = pd.read_excel('Resturants.XLSX')
## create a small restaurant dataset similar to yours
## downloaded from: https://www.kaggle.com/datasets/khushishahh/fast-food-restaurants-across-us?resource=download
df = pd.read_csv('Fast_Food_Restaurants_US.csv', nrows=100, usecols=['latitude','longitude','name'])
df.rename(columns={'latitude':'Latitude', 'longitude':'Longitude'}, inplace=True)
## randomly assign some cuisine types to unique restaurant names
unique_names = df['name'].unique()
np.random.seed(42)
name_cuisine_map = {
name:cuisine for name,cuisine in
zip(unique_names, np.random.choice(['American','Mexican','Chinese'], size=len(unique_names)))
}
cuisine_color_map = {
'American':'blue',
'Mexican':'green',
'Chinese':'red'
}
df['cusines'] = df['name'].map(name_cuisine_map)
df['color'] = df['cusines'].map(cuisine_color_map)
app.layout = html.Div([
html.H1('Resturant map by cusine', style={'text-align': 'center'} ),
dcc.Dropdown(id='cusine_dd',
options=[{'label': i, 'value': i} for i in df.cusines.unique()],
value = 'Chinese',
style={'width':'40%'}),
html.Div(id= 'output', children =[] ),
dcc.Graph(id='mapbycusine', figure={})
])
#app.callback(
[Output(component_id='output', component_property='children'),
Output(component_id='mapbycusine', component_property='figure')],
[Input(component_id='cusine_dd', component_property='value')]
)
def update_figure(input_cusine):
#cusine_filter = 'All'
container = f"Currently showing {input_cusine}"
df_copy = df.copy(deep=True)
if input_cusine:
df_copy = df_copy[df_copy['cusines'] == input_cusine]
print("\n")
print(df_copy.head())
fig = px.scatter_mapbox(data_frame=df_copy, lat='Latitude', lon='Longitude', zoom=3, height=300, hover_data= ['cusines'], color='cusines', color_discrete_map=cuisine_color_map)
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(height=1000, margin={"r":100,"t":100,"l":100,"b":300})
return container, fig
if __name__ == '__main__':
app.run_server(debug=True)

Dash RangeSlider automatically rounds marks

I am using the RangeSlider in Python Dash. This slider is supposed to allow users to select a range of dates to display, somewhere between the minimum and maximum years in the dataset. The issue that I am having is that each mark shows as 2k due to it being automatically rounded. The years range between 1784 and 2020, with a step of 10 each time. How do I get the marks to show as the actual dates and not just 2k? This is what I have below.
dcc.RangeSlider(sun['Year'].min(), sun['Year'].max(), 10,
value=[sun['Year'].min(), sun['Year'].max()], id='years')
You can use attribute marks to style the ticks of the sliders as follows:
marks={i: '{}'.format(i) for i in range(1784,2021,10)}
The full code:
from dash import Dash, dcc, html
app = Dash(__name__)
app.layout = html.Div([
dcc.RangeSlider(1784, 2020,
id='non-linear-range-slider',
marks={i: '{}'.format(i) for i in range(1784,2021,10)},
value=list(range(1784,2021,10)),
dots=False,
step=10,
updatemode='drag'
),
html.Div(id='output-container-range-slider-non-linear', style={'margin-top': 20})
])
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
Output

Mapping time-series data with Plotly Dash, but without using MapBox

I have a huge dataset with geo-location and timestamps. My goal is to map this data on an interactive dashboard where it's possible to choose the timeframe that a user wants to map. I started doing this in Plotly Dash, and I saw most of the tutorials with Mapbox, but given it's limits in the free package, it is out of the question.
Is there some other (100% free) way to still interactively map this timeseries data using Dash?
I tried converting the dataset into geojson file and adding a geojson layer, but it still didn't show the data on the map. Combining different callback options from some online tutorials also didn't result with the data showed on map but simply an empty map (left as comments in the code snippet below).
Apart from this, I chose date range picker, but given the timestamp data, I would prefer to have the date picker available in detail (DD/MM/YYYY HH:MM:SS) on the dashboard (based on the data timestamps), though I am not sure if that's even possible.
Does some have a suggestion on how to solve this?
Below I share a small part of the data:
timestamp id lat lon mode geometry
0 2022-04-01 13:48:38 15 52.5170365 13.3888599 AUTO POINT (52.5170365 13.3888599)
1 2022-04-01 13:48:40 15 52.5170365 13.3888599 AUTO POINT (52.5170365 13.3888599)
2 2022-04-01 13:48:42 15 52.5170365 13.3888599 AUTO POINT (52.5170365 13.3888599)
3 2022-04-01 13:49:18 15 52.5170375 13.3888605 AUTO POINT (52.5170375 13.3888605)
4 2022-04-01 13:49:34 15 52.5170375 13.3888605 AUTO POINT (52.5170375 13.3888605)
5 2022-04-01 13:49:52 15 52.5170375 13.3888605 AUTO POINT (52.5170375 13.3888605)
6 2022-04-01 13:50:10 15 52.5170385 13.3888609 AUTO POINT (52.5170385 13.3888609)
7 2022-04-01 13:50:46 15 52.5170385 13.3888609 AUTO POINT (52.5170385 13.3888609)
8 2022-04-01 13:51:24 15 52.5170395 13.3888614 AUTO POINT (52.5170395 13.3888614)
9 2022-04-01 13:51:46 15 52.5170395 13.3888614 AUTO POINT (52.5170395 13.3888614)
..and also the code I wrote for the map:
import dash
import dash_daq as daq
from dash import dcc, html, Input, Output
from pandas_datareader import data as web
from datetime import datetime as dt
from datetime import date
import dash_leaflet as dl
import dash_leaflet.express as dlx
from jupyter_dash import JupyterDash
import plotly.express as px
import plotly.graph_objects as go
import json
min_date='01/04/2022'
max_date=dt.today()
#gdf = #the data showed above
geojson = json.loads(gdf.to_json())
# Build the dashboard
app = JupyterDash(__name__)
app.layout = html.Div([
html.H2('Dashboard', style={'text-align':'center', 'font-family': 'sans-serif'}),
dcc.DatePickerRange(
id='date-picker-range',
min_date_allowed=min_date,
max_date_allowed=max_date,
initial_visible_month=dt(dt.today().year, 4, 1).date(),
start_date=dt(2022, 4, 1).date(),
end_date=dt.today(),
show_outside_days=True,
day_size=32,
display_format='DD/MM/YYYY',
clearable=True,
style={'text-align':'center', 'width': '100%', 'height': '60px', 'font-size': '10'}),
#dcc.Graph(id='my-graph', figure=fig),
dl.Map([
dl.TileLayer(maxZoom=20)
#dl.GeoJSON(data=geojson)
],
id='map',
center=[52.517, 13.388],
zoom=14.5,
style={'width': '400px', 'height': '400px', 'margin': "auto", "display": "block"})
])
##app.callback(
# Output("map", "figure"),
# [Input('date-picker-range', 'start_date'),
# Input('date-picker-range', 'end_date')])
if __name__ == '__main__':
app.run_server(mode="external", debug=True)

Categories