1

I'm trying to make a pie chart with 3 options:

  1. Create graph for all item when don't select dropdown options
  2. Show each graph for each item selection.
  3. Create graph for multiple item options. It's the sum of item options.

Below is my code:

import pandas as pd
import numpy as np
import plotly.express as px
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.graph_objects as go

df = pd.DataFrame({
    'invoiceTotal': [123.25,237.55,220.13,211.35,135.46],
    'itemType': ['item','service','service','service','item'],
    'Channel':['In Store','Phone Order','In Store','E-mail','Website']})

app = dash.Dash(__name__,external_stylesheets=[dbc.themes.LUX])
app.layout = html.Div([
                dbc.Row([
                        dcc.Dropdown(id='channel_type',placeholder="Channel", # Dropdown for heatmap color
                                options=[{'label':y,'value':y} for y in df.sort_values('Channel')['Channel'].unique()], 
                                multi=False,
                                disabled=False,
                                clearable=True,
                                searchable=True), 
                        dcc.Graph(id='pie-chart',figure={},style={'height':400,'width':'auto'})
                        ])
])

@app.callback(Output('pie-chart', 'figure'),
             [Input('channel_type', 'value')])

def build_graph(channeltype):
    if not channeltype or 'Select' in channeltype:    
        df1 = df.copy()
        df1_1 = pd.pivot_table(df1,('invoiceTotal'),index=['itemType'],aggfunc=np.sum).reset_index()
        df1_1['Channel'] = 'All channel'            
    else:
        df1 = df.copy()
        df1_1 = pd.pivot_table(df1,('invoiceTotal'),index=['itemType','Channel'],aggfunc=np.sum).reset_index()
        df1_1 = df1_1[(df1_1['Channel'] == channeltype)]

           
    pie_chart = px.pie(df1_1,values='invoiceTotal',names='itemType',
               color_discrete_sequence=px.colors.qualitative.Prism,hole=.3)
    pie_chart.update_traces(textinfo='percent+label',
                    title_position="top center",
                    title_font_size=18,
                    showlegend=True)
    pie_chart.update_layout(plot_bgcolor='white',margin=dict(l=20, r=20, t=20, b=20))
    pie_chart.update_yaxes(showline=False,showgrid=False)
    pie_chart.update_xaxes(showline=False,showgrid=False)     
    return pie_chart

if __name__ == "__main__":
    app.run_server(debug=False,port=1200)

It's just working for option 1 and option 2. When I change options of dropdown from False to True, it raised error that said: ValueError: ('Lengths must match to compare', (5,), (1,))

I'm curious is that anyway to make option 3. Thank you.

hoa tran
  • 1,391
  • 1
  • 5
  • 14

1 Answers1

1

The multiple selection in the dropdown should be set as multi=positive and the values received will be a mixture of single and multiple values, so the format needs to be changed to extract conditions by the values included using isin. I'm also adding a setting as an initial graph. Please verify the data yourself as we have not verified all the data.

import dash
from dash import html
from dash import dcc
import dash_bootstrap_components as dbc
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

df = pd.DataFrame({
    'invoiceTotal': [123.25,237.55,220.13,211.35,135.46],
    'itemType': ['item','service','service','service','item'],
    'Channel':['In Store','Phone Order','In Store','E-mail','Website']})

app = dash.Dash(__name__,external_stylesheets=[dbc.themes.LUX])
#app = JupyterDash(__name__,external_stylesheets=[dbc.themes.LUX])

app.layout = html.Div([
                dbc.Row([
                        dcc.Dropdown(id='channel_type',placeholder="Channel", # Dropdown for heatmap color
                                options=[{'label':y,'value':y} for y in df.sort_values('Channel')['Channel'].unique()], 
                                multi=True, # update
                                disabled=False,
                                clearable=True,
                                searchable=True), 
                        dcc.Graph(id='pie-chart',figure=pie_chart, style={'height':400,'width':'auto'}) # update
                        ])
])

@app.callback(Output('pie-chart', 'figure'),
             [Input('channel_type', 'value')])

def build_graph(channeltype):
    if not channeltype or 'Select' in channeltype:    
        df1 = df.copy()
        df1_1 = pd.pivot_table(df1,('invoiceTotal'),index=['itemType'],aggfunc=np.sum).reset_index()
        df1_1['Channel'] = 'All channel'            
    else:
        df1 = df.copy()
        df1_1 = pd.pivot_table(df1,('invoiceTotal'),index=['itemType','Channel'],aggfunc=np.sum).reset_index()
        df1_1 = df1_1[df1_1['Channel'].isin(channeltype)] # update

           
    pie_chart = px.pie(df1_1,values='invoiceTotal',names='itemType',
               color_discrete_sequence=px.colors.qualitative.Prism,hole=.3)
    pie_chart.update_traces(textinfo='percent+label',
                    title_position="top center",
                    title_font_size=18,
                    showlegend=True)
    pie_chart.update_layout(plot_bgcolor='white',margin=dict(l=20, r=20, t=20, b=20))
    pie_chart.update_yaxes(showline=False,showgrid=False)
    pie_chart.update_xaxes(showline=False,showgrid=False)     
    return pie_chart

if __name__ == "__main__":
    app.run_server(debug=False, port=1200)# mode='inline'

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32