Is it possible to display different chart types based on user input?

I want to code a conditional statement to this effect:

"If the user chooses milligrams, micrograms or grams from a radio button’s list of values, then display the data in a bar chart. If the user chooses percentage from the same list, then display it in a pie chart."

To be clear, I do not want the user to decide what kind of chart displays the data. When he or she chooses a certain unit of measurement, however, I want the code to display the data in the most appropriate kind of chart, as certain types of data are best displayed in certain charts.

This question is probably easy for an experienced Dash programmer. I should note the callbacks and functions were functional before I introduced the conditionals.

Here is my dcc.RadioItems commponent:

dcc.RadioItems(
    id='units_radio',
    options=[
        
        {'label': 'Micrograms', 'value': 'Micrograms'},
        {'label': 'Milligrams', 'value': 'Milligrams'},
        {'label': 'Grams', 'value':  'Grams'},
        {'label': 'Percentage', 'value': 'Percentage'},
        {'label': 'Calories', 'value': 'Calories'},
        ], value='Grams'
        ),

    html.Hr(),

    dcc.Graph(id='display_barcharts'),
    dcc.Graph(id='display-piecharts')
])
(The RadioItem component has not produced any errors).

# Here is the minimal, meaningful example of my latest attempt to construct the conditional statement:

It is long only because of the (necessary?) repetition. I suspect the problem lies in how I crafted the if statement, but I could not find much information online applicable to this example. My error messages tell me that "selected_units’ is not defined, which also indicates that I don’t know how to code “if value of radio item = x, then do something.”

**# If the value of the component named 'units-radio' is NOT percentage, **
**# then display the corresponding, filtered data in a bar chart.**

if 'units_radio' != "Percentage":

    @callback(
    Output('display_barcharts', 'figure'),
    Input('gender_radio', 'value'),
    Input('ages_radio', 'value'),
    Input('units_radio', 'value'))

    def return_barcharts(selected_gender, selected_ages, selected_units):

        df = pd.read_csv('final_charts_data.csv')

        Nutrients = df.Nutrients.unique()
        Amounts = df.Amounts.unique()
        Benchmarks = df.Benchmarks.unique()
        Units = df.Units.unique()
        Gender = df.Gender.unique()
        Ages = df.Ages.unique()

        data = df.loc[((df['Gender'] == selected_gender) & (df['Units'] == selected_units)) & ((df['Ages'] == selected_ages))]

        fig = go.Figure()
        fig.add_trace(go.Bar(
            x=data.Nutrients,
            y=data.Amounts,
            name='Recipe Nutrient Values',
            marker_color='midnightblue'
            ))
        fig.add_trace(go.Bar(x=data.Nutrients,
            y=data.Benchmarks,
            name='Nutritional Benchmarks',
            marker_color='orange'
            ))
        fig.update_layout(
            title='Recipe Nutrient Values vs. Nutritional Benchmarks',
            xaxis_tickfont_size=14,
            yaxis=dict(
            # title='????',
            titlefont_size=16,
            tickfont_size=14,
            ),
            legend=dict(
                x=0,
                y=1.0,
                bgcolor='rgba(255, 255, 255, 0)',
                bordercolor='rgba(255, 255, 255, 0)'
                ),
            barmode='group',
            bargap=0.15, # gap between bars of adjacent location coordinates.
            bargroupgap=0.1 # gap between bars of the same location coordinate
            )
        return fig

**# If the value of the component named 'units-radio' is 'percentage', **
** # then display the corresponding, filtered data in a pie chart.**

    @callback(
    Output("display-piecharts", "figure"),
    Input("values", "value"),
    Input('gender_radio', 'value'),
    Input('ages_radio', 'value'),
    Input('units_radio', 'value'))

    def return_piecharts(selected_gender, selected_ages, selected_units):

        df = pd.read_csv('final_charts_data.csv')

        Nutrients = df.Nutrients.unique()
        Amounts = df.Amounts.unique()
        Benchmarks = df.Benchmarks.unique()
        Units = df.Units.unique()
        Gender = df.Gender.unique()
        Ages = df.Ages.unique() 

        data = df.loc[((df['Gender'] == selected_gender) & (df['Units'] == selected_units)) & ((df['Ages'] == selected_ages))]

** # Once the user chooses percentage, a dropdown menu appears and lets the user  
# decide which nutrient value he or she wishes to explore (e.g. Percentage Total Fat vs. total calories, 
# percentage Trans Fats vs. calories, etc...)** 

    html.Div([
            html.P("Choose a chart:"),
            dcc.Dropdown(
            id='values',
            value='Total Fat',
            options=[{'value': x, 'label': x}
            for x in ['Nutrients'] if 'Units' == 'Percentage' ],
            clearable=False
            ),
            dcc.Graph(id="fats-pie-chart")
            ])
        return fig        

One thing that I have done in the past is to make it so you are outputting it to one graph, so instead of: dcc.Graph(id=‘display_barcharts’),
dcc.Graph(id=‘display-piecharts’

you would just have one:
dcc.Graph(id=‘display_charts’)

and then instead of having your if statement outside of your callback it would be within.

This would make it so that you have:
if selected_units != ‘Percentage’:
fig = specific graph
return fig

You could also include all of the inputs in the if statements or create nested ifs as well and just map out each graph.

1 Like