Switching plots with radio button screws up the format - python

I am trying to do something relatively simple. I want to create a radio button that switches between two plotting formats. The radio button switches between two options. Let us call them 'a' and 'b.'
When 'a' is selected, I want to plot two figures side by side using bootstrap row/col. When option 'b' is selected, I want to use the entire column for a single figure.
I believe I coded that correctly below, but when I switch from 'a' to 'b' and back to 'a', the plot screws up the plot and the two figures show up vertically.
import dash
from dash import dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.graph_objs as go
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(
children=html.Div(children=[
dcc.RadioItems(id='radio', options=('a', 'b'), value='a', inline=True),
dbc.Row(id='row')
])
)
#app.callback(
Output("row", "children"),
[Input("radio", "value")],
)
def fill_row(radio):
f1 = go.Figure()
f2 = go.Figure()
f3 = go.Figure()
if radio == 'a':
return [
dbc.Col(dcc.Graph(figure=f1)),
dbc.Col(dcc.Graph(figure=f2)),
]
else:
return [
dbc.Col(dcc.Graph(figure=f3)),
]
if __name__ == "__main__":
app.run_server(debug=True, port=8051)
Here are the screenshots:

The default behavior for dbc.Col components filling up a dbc.Row component is a horizontal alignment, so I can see the confusion here. However, the default size of column components is 12. And if you're trying to put two components of that size next to eachother will cause an overflow, and the columns will be stacked on top og eachother. Therefore, a possible solution is to set width = 6 for the columns in your first return statement. Or other numbers that do not sum to more than 12:
Solution
#app.callback(
Output("row", "children"),
[Input("radio", "value")],
)
def fill_row(radio):
f1 = go.Figure()
f2 = go.Figure()
f3 = go.Figure()
if radio == "a":
return [
dbc.Col([dcc.Graph(figure=f1)], width=6),
dbc.Col([dcc.Graph(figure=f2)], width=6),
]
else:
return [
dbc.Col(dcc.Graph(figure=f3), width=12),
]
Below are a few images from a test run. You'll find a complete code snippet at the end of the answer
Output 1: radio = a
Output 2: radio = b
Output 1: radio = a again
Complete code:
import dash
from dash import dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.graph_objs as go
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(
children=html.Div(
children=[
dcc.RadioItems(id="radio", options=("a", "b"), value="a", inline=True),
dbc.Row(id="row"),
]
)
)
#app.callback(
Output("row", "children"),
[Input("radio", "value")],
)
def fill_row(radio):
f1 = go.Figure()
f2 = go.Figure()
f3 = go.Figure()
if radio == "a":
return [
dbc.Col([dcc.Graph(figure=f1)], width=),
dbc.Col([dcc.Graph(figure=f2)], width=6),
]
else:
return [
dbc.Col(dcc.Graph(figure=f3), width=12),
]
# if __name__ == "__main__":
app.run_server(debug=True, port=8052)

Related

How to update marker positions in a scatter mapbox?

I'm trying to display live location data on a mapbox scatter plot. In order to mimic new data received from the server the callback moves all points every 3 seconds:
import plotly.express as px
from dash import Dash, html, dcc
from dash.dependencies import Input, Output
px.set_mapbox_access_token(open(".mapbox_token").read())
df = px.data.carshare()
app = Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='map', animate=True),
dcc.Interval(
id='interval-component',
interval=3000,
)
])
#app.callback(Output('map', 'figure'), [Input('interval-component', 'n_intervals')])
def update_map(n):
df['centroid_lon'] += 0.01
fig = px.scatter_mapbox(df, lat="centroid_lat", lon="centroid_lon")
return fig
if __name__ == '__main__':
app.run_server(debug=True)
While the labels are correctly changing their location, the markers are stuck at their original positions.
result
I found a work around by having two callbacks.
my html looks like this dbc.Col > dcc.Graph(figure = fig)
#app.callback(
Output('graph-id','figure'),
Input('control-id', 'n_clicks')
)
def update_func(scatter_map_fig):
return go.Figure
The second callback returns a new graph component with the updated information of the figure
#app.callback(
Output('col-id','children'),
Input('graph-id', 'figure'),
State('date_range','start_date'),
State('date_range','end_date'),
)
def update_func_2(scatter_map_fig):
scatter_fig = go.Figure()
scatter_fig.update_layout(...)
... (put your figure logic here)
return dcc.Graph(figure=fig)
It is a bit janky but it works until there's a better solution. Hope it helps.

Produce multiple plots using dash callbacks

I'm not clear how I could dynamically create multiple charts at once - or if that is not possible then how I could loop through a list of values using a single callback.
For example in the code below list of continents is a a list of filter options. Is it possible to basically make it so when this page loads, I see 5 charts automatically?
Currently, what I'm doing is I have to type 5 #app.callback...make_scatter_plot(option=_dropdown_value) which ends up with a million lines of code in my file and makes it hard to read even though everything is doing the same thing.
What am I missing? Thanks
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
import numpy as np
app = Dash(__name__)
df = px.data.gapminder()
list_of_continents = ["Asia", "Africa", "Europe", 'Oceania', 'Americas']
app.layout = html.Div([
html.H4('Restaurant tips by day of week'),
dcc.Dropdown(
id="dropdown",
options=list_of_continents,
multi=False
),
dcc.Graph(id="graph"),
#dcc.Graph(id ='graph2') ##????
])
#app.callback(
Output("graph", "figure"),
Input("dropdown", "value")
)
def make_scatter_plot( value =[i for i in list_of_continents], df = df):
"""
"""
data = df[df['continent'].isin([value])]
fig = px.scatter(data, x="lifeExp", y="gdpPercap",
size="pop")
return fig
if __name__ == '__main__':
app.run_server(debug=True)
although plotly express can help you set up a graph with just one line of code it’s not very handy when it comes to customizing each trace. So, for that, you’ve to switch to graphs_objects.
In the following lines of code, the callback generates a Graph component for each trace and appends each graph component to a Div component. Hence you get multiple graphs using a single callback.
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
app = Dash(__name__)
df = px.data.gapminder()
app.layout = html.Div([
html.H4('Restaurant tips by day of week'),
html.Div(id='graphs',children=[])
])
#app.callback(
Output("graphs", "children"),
Input("graphs", "children")
)
def make_scatter_plot(child):
"""
"""
for continent in df['continent'].unique():
df_filtered = df[df['continent'] == continent]
fig = go.Figure()
fig.add_trace(
go.Scatter(x = df_filtered['lifeExp'],
y = df_filtered['gdpPercap'],
mode = 'markers',
marker = dict(size = 10 + (df_filtered['pop'] - df_filtered['pop'].min()) * 20
/ (df_filtered['pop'].max() - df_filtered['pop'].min())) # This is just to scale the marker size value between 10 and 20.
)
)
fig.update_layout(
title_text = continent
)
child.append(dcc.Graph(figure=fig))
return child
if __name__ == '__main__':
app.run_server(debug=True)
The output of the Code:
Click here

Plotly/Dash - Legend selection from Plotly graph isn't cleared correctly

I have recently run into a bug regarding the legend selection from Plotly graphs in my Dash app.
I'm working with a few tabs, the last of which displays several interconnected Plotly graphs and components.
One of the graphs is considered as "the main graph", and making a selection from this graph results in changes in the other components displayed.
When switching to another tab after a selection from the legend has been made and cleared (by double-clicking on an item then double-clicking again), then switching back, a new selection from the legend will not be properly reset.
I've included a minimal code example to reproduce the behaviour:
import json
import random
import pandas as pd
pd.options.plotting.backend = "plotly"
import dash
from dash.dependencies import Input, Output, State
import dash_table as dt
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css',
"https://codepen.io/chriddyp/pen/brPBPO.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# -------------------- DATA --------------------
plot_df = pd.DataFrame({
'x': [1,2,3,4,5],
'y': [1,2,3,4,5],
'text': ['a', 'b', 'c', 'd', 'e'],
'label': [-1, -1, -1, -1, -1]
})
# -------------------- LAYOUTS --------------------
tab1_layout = html.Div(
[
html.H1('Tab 1'),
html.P('Please navigate to tab 2.')
]
)
tab2_layout = html.Div(
[
html.Div([html.H1('Tab 2')]),
# Slider
html.Div(
[
html.H3(
children=['Slider'],
),
dcc.Slider(
id="slider",
min=2,
max=5,
step=1,
value=2,
marks={
2: "2",
5: "5",
},
disabled=False,
),
]
),
# Graph
html.Div(
[
html.H3(
children=['Graph'],
),
dcc.Graph(
id="graph",
config={
'modeBarButtonsToRemove': ['autoScale2d', 'zoomIn2d', 'zoomOut2d', 'resetScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'toggleSpikelines'],
'displaylogo': False
}
),
]
),
# DataTable
html.Div(
[
html.H3(
children=['DataTable'],
),
dt.DataTable(
id='data_table',
sort_action="native",
page_action="native",
page_current= 0,
page_size= 100,
style_as_list_view=True
),
]
),
],
style={
'width':'50%',
},
)
app.layout = html.Div(
[
dcc.Store(id='store_data', data=plot_df.to_json()),
dcc.Store(id='displayed_legends'),
dcc.Tabs(
id='main_tabs',
value='tab1',
children=[
dcc.Tab(id="tab_1", label='1. Tab 1', value='tab1', children=[tab1_layout]),
dcc.Tab(id="tab_2", label='2. Tab 2', value='tab2', children=[tab2_layout])
],
),
]
)
# -------------------- CALLBACKS --------------------
#app.callback(
[Output('graph', 'figure'),
Output('store_data', 'data')],
Input('slider', 'value'),
State('store_data', 'data')
)
def update_graph_from_slider(n, data_json) :
plot_df = pd.read_json(data_json)
labels_int = list(range(0, n))
k = len(plot_df) - len(labels_int)
if k > 0:
labels_int += random.choices(range(0, n), k=k)
labels = [str(e) for e in labels_int]
plot_df['label'] = labels
plot_df = plot_df.sort_values(by='label', ascending=True)
plot_fig = plot_df.plot.scatter(x='x', y='y', hover_data={'x': False, 'y': False, 'label': True, 'text': True} ,color='label')
return plot_fig, plot_df.to_json()
#app.callback(
Output('displayed_legends', 'data'),
Input('graph', 'restyleData'),
State('displayed_legends', 'data')
)
def update_selected_legend_items(restyleEvent, displayedLegendsItems):
if displayedLegendsItems == None:
displayedLegendsItems = {}
if restyleEvent != None:
states = restyleEvent[0]['visible']
labels = restyleEvent[1]
for index in range(len(restyleEvent[0]['visible'])):
if states[index] == 'legendonly':#legend item has been deactivated
displayedLegendsItems[labels[index]] = False
elif states[index] == True:#legend item has been activated
displayedLegendsItems[labels[index]] = True
return displayedLegendsItems
#app.callback(
[Output('data_table', 'columns'),
Output('data_table', 'data'),],
[Input('graph', 'selectedData'),
Input('graph', 'relayoutData'),
Input('displayed_legends', 'data')],
State('store_data', 'data'),
)
def display_selected_data(selectedData, relayoutData, selectedTopics, data_json):
res = get_filtered_nodes(data_json, selectedTopics, selectedData)
df_table = pd.DataFrame(res)
visibility = {}
changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
if 'graph' in changed_id:
if 'relayoutData' in changed_id:
relayoutDataKeys = relayoutData.keys()
# if we zoomed, auto zoomed or rescaled,don't update the list
if 'dragmode' in relayoutDataKeys or 'xaxis.range[0]' in relayoutDataKeys or 'xaxis.autorange' in relayoutDataKeys:
res = dash.no_update
if res != dash.no_update and len(res) == 0:
visibility = {'display':'none'}
return [{"name": i, "id": i} for i in df_table.columns], df_table.to_dict('records')
# -------------------- FUNCTIONS --------------------
def get_filtered_nodes(data, selectedTopics, selectedData):
res = []
selectedTopicsKeys = selectedTopics.keys()
if selectedData != None:#There is an active selection
pointsList = json.loads(json.dumps(selectedData))
if pointsList != None and len(pointsList['points']) > 0:#Some points are selected
for point in pointsList['points']:
text = point['customdata'][1]
label = point['customdata'][0]
if label not in selectedTopicsKeys or selectedTopics[label] == True:
res.append({'text': text, 'label': label})
elif data != None:#No active selection
dataArray = json.loads(data)
textArray = dataArray['text']
if 'label' in dataArray :
labelsArray = dataArray['label']
for key in textArray.keys():
if labelsArray[key] not in selectedTopicsKeys or selectedTopics[labelsArray[key]] == True:
res.append({'text': textArray[key], 'label': labelsArray[key]})
return res
if __name__ == "__main__":
app.run_server(debug=True)
Librairies used (and their version):
pandas==1.3.3
dash==1.20.0
dash-core-components==1.16.0
dash-bootstrap-components==0.12.2
dash-html-components==1.1.3
dash-table==4.11.3
I am using python 3.9.
And here are the detailed step to replicate the bug:
run the app as usual
go to tab 2
select any item from the legend (by double-clicking on it)
clear selection (by double-clicking anywhere on the legend again)
go to tab 1
go back to tab 2
select any item from the legend (by double-clicking on it)
clear selection by double-clicking again: the datatable is not updated
optional: select new value from slider
optional: select any item from the legend (by double-clicking on it)
optional: clear selection by double-clicking yet again: this time, it works as intended (from my experiments, the bug only affects the last value where a selection has been made before switching tabs).
Looking a bit into this bug, it appears that the restyleData property from the graph, which is normally used to detect a change in selection from the legend, isn't updated when the selection is cleared and thus retains the previously selected item.
Any insight would be greatly appreciated :)

Plotly Dash dropdown menu python

I would like to add a dropdown menu to show only one figure. I mean, if I select fig the dash must show me only the fig and if I select fig2 the dash must show me the fig 2. Is it possible?
My code is an example, I have more than 500 figs.
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure()
fig2 = go.Figure()
fig.add_trace(go.Scatter(y=[4, 2, 1], mode="lines"))
fig2.add_trace(go.Bar(y=[2, 1, 3]))
figs = [fig, fig2]
div = []
for item in figs:
div.append(dcc.Graph(figure=item))
app = dash.Dash()
app.layout = html.Div(div)
"""
add a dropdown to show only one fig
"""
app.run_server(debug=True, use_reloader=False)
Yes, it is possible.
First you need to create the dropdown containing the figure-names / filenames or the identifier you wish, just keep the {'label': x, 'value': x} structure for the option parameter. label is what you will see in the dropdown, and value will be passed to the callback (s. below).
fig_names = ['fig1', 'fig2']
fig_dropdown = html.Div([
dcc.Dropdown(
id='fig_dropdown',
options=[{'label': x, 'value': x} for x in fig_names],
value=None
)])
Next you need a blank div (with an id) where the plot will appear:
fig_plot = html.Div(id='fig_plot')
Now create a callback. When an input with the id='fig_dropdown' is changed, the value parameter will be passed to the update_output function. The output of this function will be passed to passed to the children parameter of the id='fig_plot' div.
#app.callback(
dash.dependencies.Output('fig_plot', 'children'),
[dash.dependencies.Input('fig_dropdown', 'value')])
def update_output(fig_name):
return name_to_figure(fig_name)
The name_to_figure(fig_name) function returns a dcc.Graph() objects, containing your figure, depending on the fig_name value of the dropdown.
Full example:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go # or plotly.express as px
app = dash.Dash()
fig_names = ['fig1', 'fig2']
fig_dropdown = html.Div([
dcc.Dropdown(
id='fig_dropdown',
options=[{'label': x, 'value': x} for x in fig_names],
value=None
)])
fig_plot = html.Div(id='fig_plot')
app.layout = html.Div([fig_dropdown, fig_plot])
#app.callback(
dash.dependencies.Output('fig_plot', 'children'),
[dash.dependencies.Input('fig_dropdown', 'value')])
def update_output(fig_name):
return name_to_figure(fig_name)
def name_to_figure(fig_name):
figure = go.Figure()
if fig_name == 'fig1':
figure.add_trace(go.Scatter(y=[4, 2, 1]))
elif fig_name == 'fig2':
figure.add_trace(go.Bar(y=[2, 1, 3]))
return dcc.Graph(figure=figure)
app.run_server(debug=True, use_reloader=False)
Incase you have so many fig to choose from in your Drop Down box, the following changes to the code may be necessary to implement:
#app.callback(Output('fig_plot', 'figure'), [Input('fig_dropdown', 'value')])
def cb(plot_type):
plot_type = plot_type if plot_type else 'fig1'
df_year = head_db.copy()
if plot_type:
return px.bar(df_year, x='Week #', y=str(plot_type), color='Name')
#Libraries/Imports
from dash import Dash, html, dcc, Input, Output
import plotly.graph_objects as go
fig = go.Figure()
fig2 = go.Figure()
fig.add_trace(go.Scatter(y=[4, 2, 1], mode="lines"))
fig2.add_trace(go.Bar(y=2, 1, 3]))
figs = ['fig', 'fig2']
#Your HTML to display the graph
#Disables the multiple dropdown values attributes
app.layout = html.Div([
html.Div(children=[
html.label('Dropdown'),
dcc.Dropdown(id='dropdown', options=(figs), multi=False
html.div(id='show-my-graph')
])
])
#Your callback; is used to display the graph when the dropdown values are selected or updated
#app.callback(
Output(component_id='show-my-graph'), component_property='children'),
Input(component_id='dropdown', component_property='value')
)
#Defines the Function used to display the graph when an option is selected or updated
def update_graph(dropdown_value):
"Returns the appropriate graph component to display when a dropdown is selected or updated"
if(dropdown_value == 'fig'):
ret_val = dcc.Graph(id='scatter-plot-graph', figure=fig)
return ret_val
if (dropdown_value == 'fig2'):
ret_val = dcc.Graph(id='bar-graph', figure=fig2)
return ret_val
app.run_server(debug=True, use_reloader=False)

How to update a plotly graph dash with different dropdowns

I am trying to update a plotly graph dash with two different dropdowns as inputs.
This is my sample dataframe:
import pandas as pd
df1 = {'category' : ['A','A','A','B','B','B'],'subcategory' : ['x', 'y', 'z', 'x1','y1','z1'],
'x_coord' : [1, 2,3,2,2,2],'y_coord' : [1,3,2,1,3,2]}
df_test = pd.DataFrame(df1)
df_test
And what I pretend to do is if I select category A, that plots in a scatter all the correspondent points to the category, but If Also I select a subcategory that modifies the graph plotting only the correspondent category-subcategory point of the dataframe.
The code is below, and it works if I only add the callback of the first dropdown, but when I add the second callback to the subcategory it doesn't work.
I am following the suggestions in the dash plotly tutorial where it says:
A word of caution: it's not always a good idea to combine Outputs, even if you can:
If the Outputs depend on some but not all of the same Inputs, keeping them separate can avoid unnecessary updates.
If they have the same Inputs but do independent computations with these inputs, keeping the callbacks separate can allow them to run in parallel.
Dash documentation callbacks
But anyway if I put the output in separate callbacks or in the same I cannot make it work, here is the code that I am trying (using jupyter notebook):
import dash
import plotly as py
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
from jupyter_plotly_dash import JupyterDash
py.offline.init_notebook_mode(connected = True)
app = JupyterDash('Test')
app.layout = html.Div([
dcc.Dropdown(id='dropdown1',
options=[{'label':i, 'value':i} for i in df_test['category'].unique()]),
dcc.Dropdown(id='dropdown2',
options=[{'label':i, 'value':i} for i in df_test['subcategory'].unique()]),
dcc.Graph(id='graphic')
])
#app.callback(
Output('dropdown2', 'options'),
[Input('dropdown1', 'value')])
def update_drop2(selected_drop):
filtered_df = df_test[(df_test.category == selected_drop)]
return [{'label':i, 'value':i} for i in filtered_df['subcategory'].unique()]
#app.callback(
Output('graphic', 'figure'),
[Input('dropdown1', 'value')])
def update_figure(selected_drop):
filtered_df = df_test[(df_test.category == selected_drop)]
fig = go.Figure()
fig.add_trace(go.Scatter(x=filtered_df.x_coord,y=filtered_df.y_coord, marker = dict(size=15, color='green'), mode='markers'))
return fig
#app.callback(
Output('graphic', 'figure'),
[Input('dropdown2', 'value')])
def update_figure(selected_drop):
filtered_df = df_test[(df_test.subcategory == selected_drop)]
fig = go.Figure()
fig.add_trace(go.Scatter(x=filtered_df.x_coord,y=filtered_df.y_coord, marker = dict(size=15, color='green'), mode='markers'))
return fig
app
If I use multiple inputs on the callback like this:
#app.callback(
Output('graphic', 'figure'),
[Input('dropdown1', 'value'), Input('dropdown2', 'value')])
def update_figure(selected_drop1, selected_drop2):
if not selected_drop2:
filtered_df = df_test[(df_test.category == selected_drop1)]
else:
filtered_df = df_test[(df_test.category == selected_drop1) &
(df_test.subcategory == selected_drop2)]
fig = go.Figure()
fig.add_trace(go.Scatter(x=filtered_df.x_coord,y=filtered_df.y_coord,
marker = dict(size=15, color='green'), mode='markers'))
return fig
It works better (or more near what I pretend), but however when I switch between categories I see no data.
Thanks in advance for your help and reccomendations.
I had a similar problems the trick is to add to the second dropdown an option all. Then I wanted on the second dropdown to show only the subcategories in the given category. So I actually use 2 callbacks for dropdowns and 1 callback for the plot.
app.py
import pandas as pd
import os
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
df = pd.DataFrame({'category' : ['A','A','A','B','B','B'],
'subcategory' : ['x', 'y', 'z', 'x1','y1','z1'],
'x_coord' : [1, 2,3,2,2,2],
'y_coord' : [1,3,2,1,3,2]})
# lists of categories
options1 = sorted(df["category"].unique().tolist())
# dictionary of category - subcategories
all_options = df.groupby("category")["subcategory"].unique()\
.apply(list).to_dict()
# we add as first subcategory for each category `all`
for k, v in all_options.items():
all_options[k].insert(0, 'all')
app = dash.Dash()
app.layout = html.Div([
dcc.Dropdown(
id='first-dropdown',
options=[{'label': k, 'value': k} for k in all_options.keys()],
value=options1[0]
),
html.Hr(),
dcc.Dropdown(id='second-dropdown'),
html.Hr(),
dcc.Graph(id='display-selected-values')
])
# the following two callbacks generate a dynamic 2 option
#app.callback(
dash.dependencies.Output('second-dropdown', 'options'),
[dash.dependencies.Input('first-dropdown', 'value')])
def set_2_options(first_option):
return [{'label': i, 'value': i} for i in all_options[first_option]]
#app.callback(
dash.dependencies.Output('second-dropdown', 'value'),
[dash.dependencies.Input('second-dropdown', 'options')])
def set_2_value(available_options):
return available_options[0]['value']
#app.callback(
dash.dependencies.Output('display-selected-values', 'figure'),
[dash.dependencies.Input('first-dropdown', 'value'),
dash.dependencies.Input('second-dropdown', 'value')])
def update_graph(selected_first, selected_second):
if selected_second == 'all':
ddf = df[df["category"]==selected_first]
else:
ddf = df[(df["category"]==selected_first) &
(df["subcategory"]==selected_second)]
fig = go.Figure()
fig.add_trace(
go.Scatter(x=ddf["x_coord"],
y=ddf["y_coord"],
marker = dict(size=15, color='green'),
mode='markers'))
return fig
if __name__ == '__main__':
app.run_server(debug=True, port=8051)

Categories

Resources