How to trigger a mouseout event in Python Dash? - python

How can I implement a callback function that reacts to mouseout and restores a default when not hovering over a data point?
I simplified a code snipped from the 'Interactive Visualizations' section of the Plotly|Dash tutorial to illustrate my question. In this example a callback function returns the mouseover information. How do I return a default on mouseout?
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
app = dash.Dash(__name__)
df = pd.DataFrame({
"x": [1,2,1,2],
"y": [1,2,3,4]
})
fig = px.scatter(df, x="x", y="y")
fig.update_traces(marker_size=20)
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig
),
html.Div([
html.Pre(id='hover-data')
])
])
#app.callback(
Output('hover-data', 'children'),
Input('basic-interactions', 'hoverData'))
def display_hover_data(hoverData):
if hoverData:
return str(hoverData)
else:
return "hover over data point"
if __name__ == '__main__':
app.run_server(debug=True)

You can set the clear_on_unhover property on dcc.Graph:
clear_on_unhover (boolean; default False): If True, clear_on_unhover will clear the hoverData property when the user "unhovers" from a point. If False, then the hoverData property will be equal to the data from the last point that was hovered over.
So change this:
dcc.Graph(id="basic-interactions", figure=fig)
to this:
dcc.Graph(id="basic-interactions", figure=fig, clear_on_unhover=True)
On unhover hoverData will be equal to None, so the callback in the example can stay unchanged. "hover over data point" will be returned on unhover.

Related

only list-like objects are allowed to be passed to isin(), you passed a [str]

I am trying to create dashboard by using the plotly python. Require to create dropdown for date selection for the pie chart. All the data are come from a .csv file.
Expectation: The data displayed in the pie chart are based on the date selected.
Data:
enter image description here
Code:
date_category = list(df['Date'].unique())
app.layout = ...,
dcc.Dropdown(id='date_drdn', multi=False, value= ['02/01/2022'],
options = [{'label':x, 'value':x}
for x in date_category]
),
dcc.Graph(id='pie-fig', figure={})
#app.callback(
Output('pie-fig', 'figure'),
Input('date_drdn', 'value'))
def update_graph(selection):
dff = df[df['Date'].isin(selection)]
fig = px.pie(dff, values='Transactions', names='Product', color_discrete_sequence=px.colors.sequential.RdBu)
fig.update_traces(textinfo= "label+value+percent").update_layout(title_x=0.5)
return fig
However, it keep on showing the error message when select the date.
Error message:"only list-like objects are allowed to be passed to isin(), you passed a [str]"
And the data is not display based on the date selected.
Does anyone know why and how to solve it?
If the return value of the dropdown allows multiple selections, it will be in list format and isin effect. Since the expected pie chart is a single selection of date and time, the list format is not needed as an initial value. At the same time, the return value of the callback will be a single date and time data for conditional extraction.
date_category = list(df['Date'].unique())
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
#from jupyter_dash import JupyterDash
app = Dash(__name__)
#app = JupyterDash(__name__)
app.layout = html.Div([
html.H3('Daily Graph'),
dcc.Dropdown(id='date_drdn',
multi=False,
value= '02/01/2022',
options = [{'label':x, 'value':x} for x in date_category]
),
dcc.Graph(id='pie-fig', figure={})
])
#app.callback(
Output('pie-fig', 'figure'),
Input('date_drdn', 'value'))
def update_graph(selection):
# if selection:
dff = df[df['Date'] == selection]
#print(dff)
fig = px.pie(dff, values='Transactions', names='Product', color_discrete_sequence=px.colors.sequential.RdBu)
fig.update_traces(textinfo="label+value+percent").update_layout(title_x=0.5)
return fig
if __name__ == '__main__':
app.run_server(debug=True)#, mode='inline'

PlotlyDash embedding data into html.Details

im kinda new to Python and Dash.
As i'm interested in Data Analytics I started messing around with Dash.
The plan is to build a stock dashboard but i'm stuck with some things...
I want to have an dcc.Input box where you can put a Ticker and submit with html.button,
later on I want to display data from multiple stocks in different html.Details so my Question is
how to achieve that.
I'm not getting to far because I don't understand the callback.
When trying the provied code I get Error:Callback error updating table.children - AttributeError: 'NoneType' object has no attribute 'upper'
Whats the correct way to turn input into a datatable and put in a html.Details
import yfinance as yf
import pandas as pd
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output, Input, State
app = dash.Dash()
app.layout = html.Div([
dcc.Input(id='input', value='', type='text', placeholder='Enter Stock ticker'),
html.Button('Submit', id='button'),
html.Div(id='table')
])
#app.callback(
[Output('table', 'children')],
[Input('button', 'n_clicks')],
[State('input', 'value')]
)
def update_table(input_value, n_clicks):
ticker = yf.Ticker(input_value.upper())
history = ticker.history(period='max')
return html.Div([
html.Details(
dash_table.DataTable(
id='tickerdata',
columns = [{'name': i, 'id': i} for i in history.columns],
data = history,
)
)
])
if __name__ == '__main__':
app.run_server(debug=True)
The cause of the error was that the order in which the callback functions were received and the arguments of the update function were not in the correct order. n_clicks is trying to capitalize the number and the error occurred. The next error is that the data frame needs to be changed to a dictionary in order to be displayed in the table. Also, the data in the stocks is indexed by date, so the date column needs to be unindexed in order to display it.
import yfinance as yf
import pandas as pd
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Output, Input, State
app = dash.Dash()
app.layout = html.Div([
dcc.Input(id='input', value='', type='text', placeholder='Enter Stock ticker'),
html.Button('Submit', id='submit_btn',n_clicks=0),
html.Div(id='table')
])
#app.callback(
Output('table', 'children'),
[Input('submit_btn', 'n_clicks')],
[State('input', 'value')]
)
def update_table(n_clicks, input_value):
ticker = yf.Ticker(input_value.upper())
history = ticker.history(period='max')
history.reset_index(inplace=True)
return html.Div([
html.Details(
dash_table.DataTable(
id='tickerdata',
columns = [{'name': i, 'id': i} for i in history.columns],
data = history.to_dict('records'),
fixed_rows={'headers':True}
)
)
])
if __name__ == '__main__':
app.run_server(debug=True)

Columns not displaying correctly using python dash and mongo db

I am working on a project and after finally getting around some Type errors, I am finally getting my chart to display but it is listing each character in each mongo db json document instead of in proper json form. I am a total noob at this and I cannot seem to get it right so any help that can be offered in getting my interactive chart displayed as well as my pie chart and location chart will be greatly appreciated. I think the problem is derived from how the data is being entered into the dataframe but I can not figure it out.
Here is the read functions that are being used to take the info from the mongo db and send it to the Python script:
def read(self, data):
if data !=None: # checks to make sure that the received data is not null
result = self.database.animals.find(data).limit(35)
return result
else:
raise Exception("Data entered is null!")
def readAll(self, data):
found = self.database.animals.find({}).limit(35)
return(found)
Here is the code for the python script that has imported dash:
from jupyter_plotly_dash import JupyterDash
import dash
import dash_leaflet as dl
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import dash_table
from dash.dependencies import Input, Output
from bson.json_util import dumps,loads
import bson
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pymongo import MongoClient
from AAC import AnimalShelter
###########################
# Data Manipulation / Model
###########################
# FIX ME update with your username and password and CRUD Python module name
username = "aacuser"
password = "Melvin1234!"
shelter = AnimalShelter()
shelter._init_(username,password)
# class read method must support return of cursor object and accept projection json input
df =pd.DataFrame.from_records(list(dumps(shelter.readAll({}))))
dff = pd.DataFrame.from_records(list(dumps(shelter.readAll({}))))
#########################
# Dashboard Layout / View
#########################
app = JupyterDash('SimpleExample')
import base64
app.layout = html.Div([
html.Div(id='hidden-div', style={'display':'none'}),
html.Center(html.B(html.H1('SNHU CS-340 Dashboard'))),
html.Div(className='header',
children=[html.Center(html.Img(src='/home/16514911_snhu/Downloads/Grazioso Salvare Logo.jpg',width="500", height="600")), #image logo
html.Center(html.B(html.H6('Jacqueline Woods')))]), #Unique Handle
html.Br(),
html.Div(className ='row',
children=[
html.Button(id='submit-button-one',n_clicks=0, children='Cats'),
html.Button(id='submit-button-two',n_clicks=0,children='Dogs') ]),
html.Div(dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i,"age_upon_outcome":i, 'animal_id':i,'animal_type':i,'breed':i,"color":i,
'date_of_birth':i,'datetime':i,'monthyear':i,'outcome_subtype':i,'outcome_type':i,'sex_upon_outcome':i,
'location_lat':i,'location_long':i,'age_upon_outcome_in_weeks':i,
"deletable": False, "selectable": True} for i in df.columns]
,data=df.to_dict('records'),editable = False,filter_action='native')),
html.Br(),
html.Div(
dcc.Graph( #piechart
id ='graph_id',
figure=list(dumps(shelter.readAll({})))
),
title="Outcome_Type"),
html.Br(),
html.Div( #location map
id='map-id',
className='col s12 m6',
title="Location"
)])
##Interaction Between Components / Controller
#This callback will highlight a row on the data table when the user selects it
#app.callback(
Output('datatable-interactivity',"data"),
[Input('submit-button-one','n_clicks'),
Input('submit-button-two','n_clicks')
]
)
def on_click(bt1, bt2):
if(int(bt1) ==0 and int(bt2) ==0):
df =pd.DataFrame.from_records(shelter.readAll({}))
elif (int(bt1) > int(bt2)):
df = pd.DataFrame(dumps(shelter.read({"animal__type":"Cat"})))
df =pd.DataFrame(dumps(shelter.read({"animal_type":"Dog"})))
return df.to_dict('records')
#app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
[Input('datatable-interactivity', 'selected_columns')]
)
def update_styles(selected_columns):
return [{
'if': { 'column_id': i },
'background_color': '#D2F3FF'
} for i in selected_columns]
#app.callback(
Output('graph_id','figure'),
[Input('datatable-interactivity',"derived_virtual_data")])
def update_Graph(allData):
dff= pd.DataFrame(allData)
pieChart = px.pie(
data_frame=dff,
names=dff['outcome_type'],
hole = 3,
)
return pieChart
#app.callback(
Output('map-id', "children"),
[Input('datatable-interactivity', 'derived_viewport_data'),
Input('datatable-interactivity', 'derived_virtual_selected_rows')
])
def update_map(viewData):
#FIXME Add in the code for your geolocation chart
dff = pd.DataFrame.from_dict(viewData)
dff = df if viewData is None else pd.DataFrame(viewData)
selected_animal = None
if not derived_virtual_selected_rows:
slected_animal = dff.iloc[0]
else:
slected_animal = dff.iloc[derived_vertual_selected_rows[0]]
latitude = selected_animal[12]
longitude =selected_animal[13]
breed = selected_animal[3]
name = selected_animal[0]
# Austin TX is at [30.75,-97.48]
return [
dl.Map(style={'width': '1000px', 'height': '500px'}, center=[30.75,-97.48], zoom=10, children=[
dl.TileLayer(id="base-layer-id"),
# Marker with tool tip and popup
dl.Marker(position=[latitude,longitude], children=[
dl.Tooltip(breed),
dl.Popup([
html.H1("Animal Name"),
html.P(name)
])
])
])
]
app
I was in the same boat as you searching for answers online. I happened to found the answer. Hopefully, this can help others who are experiencing this problem.
#Convert the pymongo cursor into a pandas DataFrame
df = pd.DataFrame(list(shelter.readAll({})))
#Drop the _id column generated by Mongo
df = df.iloc[:, 1:]
After that, you can access the data of the DataFrame by using
df.to_dict('records')

Issue in creating bar graph on plotly dash

CODE:
app.layout=html.Div([
html.Div('WORLD HAPPINESS REPORT',
style={
'textAlign':'center',
'color':'#F197C0',
'fontWeight':'bold',
'fontSize':'50px',
'fontFamily':'Sans-serif',
'border':({"width":"2px", "color":"black"})
}),
html.P('''The World Happiness Report is an annual report on the state of global happiness
and is currently participated by 155 countries. ''',
style={
'textAlign':'justify-text',
'color':'#B49FDC',
'fontWeight':'bold',
'fontSize':'15px',
'fontFamily':'Sans-serif'
}),
#for dropdown
html.Br(),
dcc.Dropdown(id='select_year',
options=[
{'label':'2015','value':2015},
{'label':'2016','value':2016},
{'label':'2017','value':2017},
{'label':'2018','value':2018},
{'label':'2019','value':2019},
{'label':'2020','value':2020},
],
multi=False,
value='2015',
style={'width': "40%"}
),
dcc.Graph(id='the_graph',figure={})
])
#app.callback(
Output(component_id='the_graph', component_property='figure'),
[Input(component_id='select_year', component_property='value')] #this is for the argument of the func.written below.
)
def update_graph(option_selected):
#print(option_slctd)
#print(type(option_slctd))
#container = "The year chosen by user was: {}".format(option_slctd)
#if option_selected==2015:
d1=data[data['Year']==option_selected]
fig=go.Bar(
x=df1['Country'],
y=df1['Happiness Score']
)
return fig
I have to make a bar graph using plotly dash. But i am not getting the required output.I am not able to understand as to why the outcome is coming like that.
The output that im getting is :
Can anyone please let me know what the issue is with the code ?
I think the reason you didn't get a graph is because you were missing go.Figure(). Since I don't have the same data you are using, I used the data used on the official website and modified the dropdown values to match the data. The environment I verified is JupyterLab, so there is some code about it, but please ignore it.
import dash
import dash_core_components as dcc
import dash_html_components as html
#from jupyter_dash import JupyterDash
from dash.dependencies import Input, Output, State
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
data = px.data.gapminder()
#app = JupyterDash(__name__)
app = dash.Dash(__name__)
app.layout = html.Div([html.Div('WORLD HAPPINESS REPORT',
style={'textAlign':'center',
'color':'#F197C0',
'fontWeight':'bold',
'fontSize':'50px',
'fontFamily':'Sans-serif',
'border':({"width":"2px", "color":"black"})
}),
html.P('''The World Happiness Report is an annual report on the state of global happiness
and is currently participated by 155 countries. ''',
style={'textAlign':'justify-text',
'color':'#B49FDC','fontWeight':'bold',
'fontSize':'15px',
'fontFamily':'Sans-serif'}),#for dropdown
html.Br(),
dcc.Dropdown(id='select_year',
options=[
{'label':'1982','value':1982},
{'label':'1987','value':1987},
{'label':'1992','value':1992},
{'label':'1997','value':1997},
{'label':'2002','value':2002},
{'label':'2007','value':2007},],
multi=False,
value='2015',
style={'width': "40%"}),
dcc.Graph(id='the_graph',figure={})
])
#app.callback(
Output(component_id='the_graph', component_property='figure'),
[Input(component_id='select_year', component_property='value')] #this is for the argument of the func.written below.
)
def update_graph(option_selected):
df1=data[data['year'] == option_selected]
fig=go.Figure(data=[go.Bar(x=df1['country'], y=df1['lifeExp'])])
return fig
if __name__ == "__main__":
app.run_server()
#app.run_server(mode='inline')

"I am trying get the values of the single row based on drop down value selected. getting error with output."

"I am trying to get the values of the single row based on the drop-down value selected.
I am confirming the output to ensure I can do a bar plot on the same late." need your expertise help fr the same.
Any otherr ways to call the same. Thanks for your help in advance.
code :
import dash
import pandas as pd
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
df = pd.read_csv('E:\pylab\dshlab\my_dash_app\solar.csv')
app = dash.Dash()
dpdown = []
for i in df['state']:
str(dpdown.append({'label':i,'value':(i)}))
app.layout = html.Div([
html.H4('Select your State'),
dcc.Dropdown(id='dropdown', style={'height': '30px', 'width': '100px'}, options=dpdown,
value=df['state']),
#dcc.Graph(id='graph'),
html.Div(id='table-container')
])
#app.callback(
dash.dependencies.Output('table-container','children'),
[dash.dependencies.Input('dropdown', 'value')])
def display_table(dpdown):
return(df[df['state']==dpdown])
if __name__ == '__main__':
app.run_server(debug=True)
Error:
ash.exceptions.InvalidCallbackReturnValue:
The callback for <Outputtable-container.children>
returned a value having type DataFrame
which is not JSON serializable.
The value in question is either the only value returned,
or is in the top level of the returned list,
and has string representation
state Number of Solar Plants Installed Capacity (MW) Average MW Per Plant Generation (GWh)
1 Arizona 48 1078 22.5 2550
In general, Dash properties can only be
dash components, strings, dictionaries, numbers, None,
or lists of those.
I used dash_table for creation of the table. You can read more about it here.
Code is as follows:
import dash
import pandas as pd
import dash_core_components as dcc
import dash_html_components as html
import dash_table as dt
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
df = pd.read_csv('E:\pylab\dshlab\my_dash_app\solar.csv')
app = dash.Dash()
dpdown = []
for i in df['state']:
str(dpdown.append({'label':i,'value':(i)}))
app.layout = html.Div([
html.H4('Select your State'),
dcc.Dropdown(id='dropdown', style={'height': '30px', 'width': '100px'}, options=dpdown),
#dcc.Graph(id='graph'),
html.Div(
id='table-container',
className='tableDiv'
)
])
#app.callback(
dash.dependencies.Output('table-container','children'),
[dash.dependencies.Input('dropdown', 'value')])
def display_table(dpdown):
df_temp = df[df['state']==dpdown]
return html.Div([
dt.DataTable(
id='main-table',
columns=[{'name': i, 'id': i} for i in df_temp.columns],
data=df_temp.to_dict('rows')
)
])
if __name__ == '__main__':
app.run_server(debug=True)
This will temporarily subset the dataframe and filter for your state every time a callback occurs, and output only the row corresponding to the state.

Categories