Scatter plot color and clickData mismatch - python

I'm trying to make interactive graphs based on hover_data and using this doc for reference. And below is code from this doc.
from dash import Dash, html, dcc, Input, Output
import pandas as pd
import plotly.express as px
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
df['Indicator Name'].unique(),
'Fertility rate, total (births per woman)',
id='crossfilter-xaxis-column',
),
dcc.RadioItems(
['Linear', 'Log'],
'Linear',
id='crossfilter-xaxis-type',
labelStyle={'display': 'inline-block', 'marginTop': '5px'}
)
],
style={'width': '49%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
df['Indicator Name'].unique(),
'Life expectancy at birth, total (years)',
id='crossfilter-yaxis-column'
),
dcc.RadioItems(
['Linear', 'Log'],
'Linear',
id='crossfilter-yaxis-type',
labelStyle={'display': 'inline-block', 'marginTop': '5px'}
)
], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})
], style={
'padding': '10px 5px'
}),
html.Div([
dcc.Graph(
id='crossfilter-indicator-scatter',
hoverData={'points': [{'customdata': 'Japan'}]}
)
], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}),
html.Div([
dcc.Graph(id='x-time-series'),
dcc.Graph(id='y-time-series'),
], style={'display': 'inline-block', 'width': '49%'}),
html.Div(dcc.Slider(
df['Year'].min(),
df['Year'].max(),
step=None,
id='crossfilter-year--slider',
value=df['Year'].max(),
marks={str(year): str(year) for year in df['Year'].unique()}
), style={'width': '49%', 'padding': '0px 20px 20px 20px'})
])
#app.callback(
Output('crossfilter-indicator-scatter', 'figure'),
Input('crossfilter-xaxis-column', 'value'),
Input('crossfilter-yaxis-column', 'value'),
Input('crossfilter-xaxis-type', 'value'),
Input('crossfilter-yaxis-type', 'value'),
Input('crossfilter-year--slider', 'value'))
def update_graph(xaxis_column_name, yaxis_column_name,
xaxis_type, yaxis_type,
year_value):
dff = df[df['Year'] == year_value]
fig = px.scatter(x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
hover_name=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name']
)
fig.update_traces(customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'])
fig.update_xaxes(title=xaxis_column_name, type='linear' if xaxis_type == 'Linear' else 'log')
fig.update_yaxes(title=yaxis_column_name, type='linear' if yaxis_type == 'Linear' else 'log')
fig.update_layout(margin={'l': 40, 'b': 40, 't': 10, 'r': 0}, hovermode='closest')
return fig
def create_time_series(dff, axis_type, title):
fig = px.scatter(dff, x='Year', y='Value')
fig.update_traces(mode='lines+markers')
fig.update_xaxes(showgrid=False)
fig.update_yaxes(type='linear' if axis_type == 'Linear' else 'log')
fig.add_annotation(x=0, y=0.85, xanchor='left', yanchor='bottom',
xref='paper', yref='paper', showarrow=False, align='left',
text=title)
fig.update_layout(height=225, margin={'l': 20, 'b': 30, 'r': 10, 't': 10})
return fig
#app.callback(
Output('x-time-series', 'figure'),
Input('crossfilter-indicator-scatter', 'hoverData'),
Input('crossfilter-xaxis-column', 'value'),
Input('crossfilter-xaxis-type', 'value'))
def update_y_timeseries(hoverData, xaxis_column_name, axis_type):
country_name = hoverData['points'][0]['customdata']
dff = df[df['Country Name'] == country_name]
dff = dff[dff['Indicator Name'] == xaxis_column_name]
title = '<b>{}</b><br>{}'.format(country_name, xaxis_column_name)
return create_time_series(dff, axis_type, title)
#app.callback(
Output('y-time-series', 'figure'),
Input('crossfilter-indicator-scatter', 'hoverData'),
Input('crossfilter-yaxis-column', 'value'),
Input('crossfilter-yaxis-type', 'value'))
def update_x_timeseries(hoverData, yaxis_column_name, axis_type):
dff = df[df['Country Name'] == hoverData['points'][0]['customdata']]
dff = dff[dff['Indicator Name'] == yaxis_column_name]
return create_time_series(dff, axis_type, yaxis_column_name)
if __name__ == '__main__':
app.run_server(debug=True)
With this code, every dots colored blue and I want to color dots based on Country name and I added to fig as below:
fig = px.scatter(x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
hover_name=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
color=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name']
)
But after adding color, it didn't return exact Country name when hover over dots.
Before adding color:
After adding color:
What should I do in this case. Thank you.

Use hovertext instead of customdata : just replace the occurrences in dcc.Graph() and in the callbacks, and remove the line
fig.update_traces(customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'])
This is because hovertext refers to the hover_name value of the data point being hovered, which in your case is the country name.
Actually, hoverData already receives (in callbacks) the 'x', 'y', and 'hover_name' data from the figure, so you would refer to customdata only in cases when you need other information set via custom_data or hover_data, for example in the function update_graph() :
country = dff[dff['Indicator Name'] == yaxis_column_name]['Country Name']
dff = pd.DataFrame({
'x': dff[dff['Indicator Name'] == xaxis_column_name]['Value'].values,
'y': dff[dff['Indicator Name'] == yaxis_column_name]['Value'].values,
'country': country,
'other': country.map('TEST : {}'.format), # another column
})
fig = px.scatter(x='x', y='y',
data_frame=dff,
hover_name='country',
color='country',
custom_data=['other']
)
... would let you retrieve data from other in the callbacks :
country_name = hoverData['points'][0]['hovertext']
other = hoverData['points'][0]['customdata'][0]
# [0] because 'other' is the first element in custom_data list.

Related

Aligning the height of the first and second column in Python Dash app

I have a probably simple problem that I cannot solve. I have two columns in my Python Dash dashboard, which are not aligned in height, see here:
What do I need to change in my code so that the two columns are on the same height?
Any help is much appreciated.
This is my code:
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div([
html.Label('Material 1'),
dcc.Dropdown(
id='s1m1s',
options=[{'label': i, 'value': i} for i in available_indicators],
value=options1[0],
),
html.Label('Material 1'),
dcc.Dropdown(
id='s1mdf45',
options=[{'label': i, 'value': i} for i in available_indicators],
value=options1[0],
),
], style={'width': '20%', 'display': 'inline-block'}),
html.Div([
html.Label('m3'),
daq.NumericInput(
id='s2m1_num',
min=0,
max=200,
value=0,
),
html.Label('m3'),
daq.NumericInput(
id='s2m2_num',
min=0,
max=200,
value=0,
),
], style={'width': '20%', 'display': 'inline-block'})
])
You can add 'vertical-align': 'top' to the style dictionaries of the two columns to make sure that they are aligned at the top, see below.
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_daq as daq
app = dash.Dash(__name__)
app.layout = html.Div([
# first column
html.Div(
children=[
html.Label('Material 1'),
dcc.Dropdown(
id='s1m1s',
options=[{'label': i, 'value': i} for i in ['option_1', 'option_2', 'option_3']],
value='option_1',
),
html.Label('Material 1'),
dcc.Dropdown(
id='s1mdf45',
options=[{'label': i, 'value': i} for i in ['option_1', 'option_2', 'option_3']],
value='option_2',
),
],
style={
'width': '20%',
'display': 'inline-block',
'vertical-align': 'top',
}
),
# second column
html.Div(
children=[
html.Label('m3'),
daq.NumericInput(
id='s2m1_num',
min=0,
max=200,
value=0,
),
html.Label('m3'),
daq.NumericInput(
id='s2m2_num',
min=0,
max=200,
value=0,
),
],
style={
'width': '20%',
'display': 'inline-block',
'vertical-align': 'top',
}
)
])
if __name__ == '__main__':
app.run_server(debug=True, host='127.0.0.1')

Invalid prop for this component

I'm running this app using Python Dash .I keep getting this error even though the app is loading for me perfectly. Can you please help me spot where I'm going wrong?
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objects as go
from dash.dependencies import Input, Output
import plotly.express as px
df = px.data.tips()
sales1 = pd.read_csv("sales_data_sample.csv", encoding='unicode_escape')
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div([
html.Label('Process Monitoring Dashboard',style={'font-size':'25px','color':'blue','margin-left': '50%'},id='w_countries')
]),
html.P("Process End Date",style={'margin-left': '10%'}),
dcc.Dropdown(
id='ped',
value='-Select Process End Date',
options=[{'value': x, 'label': x}
for x in ['2021', '2022', '2023', '2024']],
clearable=False,
style={'width': '30%','margin-left': '10%'}
),
html.P("User Or Role",style={'margin-left': '10%'}),
dcc.Dropdown(
id='uor',
value='-Select User Or Role',
options=[{'value': x, 'label': x}
for x in ['Admin', 'Guest User']],
clearable=False,
style={'width': '30%','margin-left': '10%'}
),
html.P("Process Start Date",style={'margin-left': '10%'}),
dcc.Dropdown(
id='psd',
value='-Select Process Start Date',
options=[{'value': x, 'label': x}
for x in ['2021', '2022', '2023', '2024']],
clearable=False,
style={'width': '30%','margin-left': '10%'}
),
html.P("Process",style={'margin-left': '10%'}),
dcc.Dropdown(
id='p',
value='-Select Process',
options=[{'value': x, 'label': x}
for x in ['Disputed','In Process','On Hold','Resolved','Cancelled']],
clearable=False,
style={'width': '30%','margin-left': '10%'}
),
# Create pie chart
html.Div([
html.Br(),
dcc.Graph(id='pie',
config={'displayModeBar': 'hover'}),
],style={'margin-left': '1.4%', 'width': '50%', 'display': 'inline-block'}),
# Create horizontal bar chart (top 10 countries)
html.Div([
html.Br(),
dcc.Graph(id='top_10',
config={'displayModeBar': 'hover'}),
], style={'width': '48.6%', 'display': 'inline-block', 'float': 'right'})
])
#app.callback(Output('pie', 'figure'),
[Input('w_countries', 'value')])
def display_content(w_countries):
Cancelled = sales1.loc[sales1['STATUS'] == 'Cancelled'].count()[0]
Disputed = sales1.loc[sales1['STATUS'] == 'Disputed'].count()[0]
In_Process = sales1.loc[sales1['STATUS'] == 'In Process'].count()[0]
On_Hold = sales1.loc[sales1['STATUS'] == 'On Hold'].count()[0]
Resolved = sales1.loc[sales1['STATUS'] == 'Resolved'].count()[0]
Shipped = sales1.loc[sales1['STATUS'] == 'Shipped'].count()[0]
return {
'data': [go.Pie(labels=['Cancelled', 'Disputed', 'In Process', 'On Hold', 'Resolved', 'Shipped'],
values=[Cancelled, Disputed, In_Process, On_Hold, Resolved, Shipped],
hoverinfo='label+value+percent',
textinfo='label+value',
textposition='auto',
textfont=dict(size=13),
insidetextorientation='radial',
rotation=70,
)],
'layout': go.Layout(
width=780,
height=520,
hovermode='closest',
title={
'text': 'Instance By Process',
'y': 0.93,
'x': 0.43,
'xanchor': 'center',
'yanchor': 'top'},
titlefont={'family': 'Oswald',
'color': 'rgb(230, 34, 144)',
'size': 25},
legend={
'orientation': 'h',
'bgcolor': 'rgba(255,255,255,0)',
'xanchor': 'center', 'x': 0.5, 'y': -0.05},
),
}
# Create horizontal bar chart (top 10 countries)
#app.callback(Output('top_10', 'figure'),
[Input('w_countries', 'value')])
def update_graph(w_countries):
top_countries = sales1.groupby(['COUNTRY'])[['SALES', 'QUANTITYORDERED']].sum().sort_values(by=['SALES'], ascending=False).nlargest(10, columns=['SALES']).reset_index()
return {
'data': [go.Bar(x=top_countries['SALES'],
y=top_countries['COUNTRY'],
text=top_countries['SALES'],
texttemplate='%{text:.2s}',
textposition='inside',
marker=dict(
color=top_countries['SALES'],
colorscale='portland',
showscale=False),
orientation='h',
hoverinfo='text',
hovertext=
'<b>Country</b>: ' + top_countries['COUNTRY'].astype(str) + '<br>' +
'<b>Sales</b>: $' + [f'{x:,.0f}' for x in top_countries['SALES']] + '<br>' +
'<b>Q.Ordered</b>: $' + [f'{x:,.0f}' for x in top_countries['QUANTITYORDERED']] + '<br>'
)],
'layout': go.Layout(
width=780,
height=520,
# plot_bgcolor='rgb(250, 242, 242)',
# paper_bgcolor='rgb(250, 242, 242)',
title={
'text': 'Top 10 Countries with active customers',
'y': 0.93,
'x': 0.43,
'xanchor': 'center',
'yanchor': 'top'},
titlefont={'family': 'Oswald',
'color': 'rgb(230, 34, 144)',
'size': 25},
hovermode='closest',
xaxis=dict(title='<b>Sales</b>',
color='rgb(230, 34, 144)',
showline=True,
showgrid=True,
showticklabels=True,
linecolor='rgb(104, 204, 104)',
linewidth=2,
ticks='outside',
tickfont=dict(
family='Arial',
size=12,
color='rgb(17, 37, 239)'
)
),
yaxis=dict(title='<b>Country</b>',
autorange='reversed',
color='rgb(230, 34, 144)',
showline=True,
showgrid=False,
showticklabels=True,
linecolor='rgb(104, 204, 104)',
linewidth=2,
ticks='outside',
tickfont=dict(
family='Arial',
size=12,
color='rgb(17, 37, 239)'
)
)
)
}
if __name__ == '__main__':
app.run_server(debug=True)
And this is my error
Invalid prop for this component
Property "value" was used with component ID:
"w_countries"
in one of the Input items of a callback.
This ID is assigned to a dash_html_components.Label component
in the layout, which does not support this property.
This ID was used in the callback(s) for Output(s):
pie.figure
top_10.figure
You've told Dash to use the value from a Label component as an input for your callback. But Label doesn't have a value, and it isn't interactive like that. You need to use a different input for that callback.

How to feed the x and y values of a Plotly bar chart from a Pandas data frame

I have the following toy data set:
df = pd.DataFrame({'Make':['Ford', 'Ford', 'Ford', 'BMW', 'BMW', 'BMW', Mercedes', 'Mercedes', 'Mercedes'],
'Score':['88.6', '76.6', '100', '79.1', '86.8', '96.4', '97.3', '98.7', '98.5'],
'Dimension':['Speed', 'MPG', 'Styling', 'Speed', 'MPG', 'Styling', 'Speed', 'MPG', 'Styling'],
'Month':['Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19']})
I'm using Plotly and the Dash framework to build an interactive web-based dashboard. The code is as follows:
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
import dash_table
import pandas as pd
app = dash.Dash()
app.layout = html.Div([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
# Allow multiple files to be uploaded
multiple=True
),
html.Div(id='output-data-upload'),
])
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns]
),
html.Hr(), # horizontal line
#### How to get the x and y values DYNAMICALLY from the data frame to pass into the Bar() function? ####
dcc.Graph(
figure = go.Figure(data=[
go.Bar(name=df.columns.values[0], x=pd.unique(df['Make']), y=[88.6, 76.6, 100], text=[88.6, 76.6, 100], textposition='auto'),
go.Bar(name=df.columns.values[1], x=pd.unique(df['Make']), y=[92.5, 93.6, 93.4], text=[92.5, 93.6, 93.4], textposition='auto'),
go.Bar(name=df.columns.values[2], x=pd.unique(df['Make']), y=[99.1, 99.2, 95.9], text=[99.1, 99.2, 95.9], textposition='auto'),
])
),
html.Hr(),
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:200] + '...', style={
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
#app.callback(Output('output-data-upload', 'children'),
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [
parse_contents(c, n, d) for c, n, d in
zip(list_of_contents, list_of_names, list_of_dates)]
return children
if __name__ == '__main__':
app.run_server(debug=True)
In summary, the user uploads a .csv file and a Pandas data frame is created. A bar plot is then rendered based on the data in the data frame.
As you can see, the go.Bar() function has x and y values that come from the df dataframe. The number of x values can fluctuate (in this case, it's 3, but it could be 2 or 10 or anywhere in between). I have the x values hard-coded in a very inelegant way as indexed values from the column names.
Questions:
1) What's the most Pythonic way to read in the x values dynamically, such that the code accepts a variable number of x values?
2) What is the best way to read in the associated y values dynamically from the df data frame? (I have them completely hard-coded in for the purposes of this example)
Thanks in advance?
did you try it in this way?
dcc.Graph(
figure = go.Figure(data=[
go.Bar(name=df.columns.values[0], x=pd.unique(df['Make']), y=df['Score'], text=df['Score'], textposition='auto'),
go.Bar(name=df.columns.values[1], x=pd.unique(df['Make']), y=df['Score'], text=df['Score'], textposition='auto'),
go.Bar(name=df.columns.values[2], x=pd.unique(df['Make']), y=df['Score'], text=df['Score'], textposition='auto'),
])
),

Python Dash - Graph not updating upon selecting new dropdown value

Hey guys,
I’m an intern python developer and I just found out about dash and Plotly, its amazing!
For my app I’m using a dataset containing info about fortune 500’s revenue in 1955-2005 period.
The problem I have is that the graph won’t update itself upon selecting additional company from the dropdown list, however, if I select a new company and delete a previous one - then the graph updates. It seems like something prevents the graph to show multiple lines at once. Also, is there any way I could add the legend telling which color is what company? Below is my code:
import dash
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
#Read CSV and change col. names
df = pd.read_csv('fortune500-full.csv')
df.columns = ['Year', 'Rank', 'Company', 'Revenue', 'Profit']
#Get a list of unique company names
Companies = df['Company'].unique()
#Stylesheet
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
#App layout
app.layout = html.Div([
#Dropdown
html.Div([
html.Label('Dropdown'),
dcc.Dropdown(
id = 'Dropdown',
options=[{'label': i, 'value': i} for i in Companies],
value=["General Motors"],
multi = True
),]),
#Graph
dcc.Graph(
id='Graph',
figure={
'data': [
go.Scatter(
x=df.loc[df['Company'] == i, 'Year'],
y=df.loc[df['Company'] == i, 'Revenue'],
text =df.loc[df['Company'] == i, 'Company'],
mode='lines',
name=i
) for i in df.Company.unique()],
'layout': go.Layout(
xaxis={'title': 'Year'},
yaxis={'title': 'Revenue'},
margin={'l': 50, 'b': 30, 't': 10, 'r': 0},
legend={'x': 1, 'y': 1},
hovermode='closest'
)}),
html.Div(dcc.RangeSlider(
id='Slider',
min=df['Year'].min(),
max=df['Year'].max(),
value=[1955, 2005],
marks={str(year): str(year) for year in df['Year'].unique()}
), style={'width': '98%', 'padding': '0px 20px 20px 20px'}),
html.Div(id='Output_slider',
style={'textAlign': 'center', 'color': ['#7FDBFF']}
)])
#app.callback(
dash.dependencies.Output('Graph', 'figure'),
[dash.dependencies.Input('Dropdown', 'value')])
def callback_a(dropdown_value):
trace = []
for val in dropdown_value:
trace.append(
go.Scatter(
x=df.loc[df['Company'] == val, 'Year'],
y=df.loc[df['Company'] == val, 'Revenue'],
text =df.loc[df['Company'] == val, 'Company'],
mode='lines',
name=val
),)
layout = go.Layout(
xaxis={'title': 'Year'},
yaxis={'title': 'Revenue'},
margin={'l': 50, 'b': 30, 't': 10, 'r': 0},
legend={'x': 1, 'y': 1},
hovermode='closest'
)
figure = {'data': trace, 'layout': layout}
return figure
#app.callback(
dash.dependencies.Output('Output_slider', 'children'),
[dash.dependencies.Input('Slider', 'value')])
def update_output(value):
return 'Wybrane lata: "{}"'.format(value)
#App
if __name__ == '__main__':
app.run_server(debug=True)
Could any of you please take a look at this and help me find root of this problem?
Kind regards.

Pandas 'key' error while creating charts through Dash

I am trying to create a scatter plot between two metrics after asking for the dimension level drill down. However, I am getting the the error: KeyError: u’brand’(one of the column names). I am new do Dash and cannot debug the error because there is nothing wrong with the column name. Following is the code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import sqlalchemy as sq
import numpy as np
from datetime import datetime
engine_prd = sq.create_engine(“connection url”)
df=pd.read_sql(“SELECT t1.date,
t1.article_type as article_type,
t1.product_gender as product_gender,
t1.brand as brand,
t1.master_category as master_category,
t1.business_unit as business_unit,
SUM(t1.revenue) as revenue,
SUM(t1.sold_quantity) as units_sold,
SUM(t1.total_discount) / NULLIF( SUM(t1.total_mrp),0) AS discount_perc,
SUM(t1.approved_po_quantity) - SUM(t1.po_inwarded_quantity) AS pending_invard_quantity,
SUM(t1.revenue) / NULLIF(SUM(t1.list_count), 0) AS rpi,
SUM(t1.list_count),
100 *ratio_to_report(SUM(t1.list_count)) OVER (PARTITION BY t1.DATE) AS lc_share
FROM fact_category_over_view_metrics t1
WHERE t1.DATE> 20180101 and is_live_style=1
GROUP BY
t1.DATE,t1.article_type,t1.product_gender,t1.brand,t1.master_category,
t1.business_unit;”,engine_prd)
df[[‘date_format’]] = df[[‘date’]].applymap(str).applymap(lambda s: “{}/{}/{}”.format(s[4:6],s[6:], s[0:4]))
df[[‘year_month’]]=df[[‘date’]].applymap(str).applymap(lambda s: “{}-{}”.format(s[0:4],s[4:6]))
df[‘year_month’]=df[‘year_month’].astype(str)
year_month=df[‘year_month’].unique()
available_indicators = np.array([‘revenue’,‘units_sold’,‘discount_perc’,‘pending_invard_quantity’,‘rpi’,‘lc_share’])
dimension_level=np.array([‘brand’,‘product_gender’,‘article_type’,‘master_category’,‘business_unit’])
#available_indicators=list(df)
app=dash.Dash()
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
id='dimension-level',
options=[{'label': i, 'value': i} for i in dimension_level],
value='brand'
)]),
html.Div([
dcc.Dropdown(
id='crossfilter-xaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='revenue'
),
dcc.RadioItems(
id='crossfilter-xaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
],
style={'width': '48%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='crossfilter-yaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='units_sold'
),
dcc.RadioItems(
id='crossfilter-yaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
], style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
]),
dcc.Graph(
id='crossfilter-indicator-scatter'),
dcc.Slider(
id='crossfilter-year-month--slider',
min=0,
max=len(df['year_month'].unique()),
value=0,
step=None,
marks={i : str(yearm) for i, yearm in enumerate(df['year_month'].unique())} # enumerate the dates
)
])
#app.callback(
dash.dependencies.Output(‘crossfilter-indicator-scatter’, ‘figure’),
[dash.dependencies.Input(‘dimension-level’, ‘value’),
dash.dependencies.Input(‘crossfilter-xaxis-column’, ‘value’),
dash.dependencies.Input(‘crossfilter-yaxis-column’, ‘value’),
dash.dependencies.Input(‘crossfilter-xaxis-type’, ‘value’),
dash.dependencies.Input(‘crossfilter-yaxis-type’, ‘value’),
dash.dependencies.Input(‘crossfilter-year-month–slider’, ‘value’)],
[dash.dependencies.State(‘crossfilter-year-month–slider’, ‘marks’)])
def update_graph(dimension_level_name,xaxis_column_name, yaxis_column_name,xaxis_type, yaxis_type, selected_year_month_key,marks):
selected_year_month=marks[str(selected_year_month_key)]
df_filtered = df[df['year_month'] == selected_year_month]
dff=df_filtered.groupby([dimension_level_name]).sum()
return {
'data': [go.Scatter(
x=dff[xaxis_column_name],
y=dff[yaxis_column_name],
text=dff[dimension_level_name],
#customdata=dff['article_type'],
mode='markers',
marker={
'size': 15,
'opacity': 0.5,
'line': {'width': 0.5, 'color': 'white'}
}
)],
'layout': go.Layout(
xaxis={
'title': xaxis_column_name,
'type': 'linear' if xaxis_type == 'Linear' else 'log'
},
yaxis={
'title': yaxis_column_name,
'type': 'linear' if yaxis_type == 'Linear' else 'log'
},
margin={'l': 40, 'b': 30, 't': 10, 'r': 0},
height=450,
hovermode='closest'
)
}
if name == ‘main’:
app.run_server()
The errors occurs while grouping by the df using the input value from dropdown. The data frame’s head looks has been linked to The sample data:
The key error occurs in "text=dff[dimension_level_name]". It is because while grouping by the dataframe , as_index is not set to False. This will throw a key error. The problem was solved by replacing dff=df_filtered.groupby([dimension_level_name]).sum() with:
dff=df_filtered.groupby([dimension_level_name].as_index=False).sum()

Categories