How can I construct a particular pie chart

I have watched all the videos several times, and played with the templates.

I am still struggling to construct a dropdown with a pie chart that shows fat ratios (e.g. trans fats, monounsaturated fats, etc…) vs. total calories depending on what fat the user chooses from the dropdown.

I constructed a special dataframe that seems to meet the needs. I created a successful dropdown that interacts with the pie chart and display the correct value. But I cannot make the pie chart display the ratio of that fat to total calories.

I feel like this should be easy, and I have probably over-thought the matter. I guess the real question is…

How do I force it - the pie chart - to show the percentage of a given fat versus total calories?

My app takes a culinary recipe as a block of text and returns a nutritional profile.

This is the dataframe (new_df) I extracted from the total nutritional profile:

 Total Fat  Saturated Fats  Monounsaturated Fats  Polyunsaturated Fats  Trans Fats  Total Calories
 0.065        0.01                    0.02                                   0.025                               0.01            1,562.38

This is my code. I cannot make it produce a pie chart that shows the percentage of a given kind of fat (or total fats) versus the total calories. It is also extra challenging in a multi-page app.

The templates don’t seem to support that task at hand.

But I could be just a little brain dead at this point.

Your thoughts and assistance would be sincerely appreciated.

Thank you for reviewing my question.

Robert

dash.register_page(__name__, suppress_callback_exceptions=True, external_stylesheets=[dbc.themes.SUPERHERO])

# Read the entire csv file from the final results file.

df = pd.read_csv("final_charts_data.csv")
dff = pd.DataFrame.from_dict(df)

# Identified all the columns in the spreadsheet

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

# Calculated the total calories for the recipe.

calories = dff[dff['Units'] == 'Calories']
avg_tot_cal = round(sum(calories.Amounts)/len(calories.Amounts),2)

# Gathered all the values of the different types of fats for the recipe.

trans_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Trans Fats'))]
all_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Fat, total'))]
sat_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Saturated Fat'))]
mono_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Monounsaturated Fats'))]
poly_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Polyunsaturated Fats'))]

# Calculated all the average values of the different types of fats for the recipe.

avg_trans_fats = round(sum(trans_fats.Amounts)/len(trans_fats.Amounts),2)
avg_all_fats = round(sum(all_fats.Amounts)/len(all_fats.Amounts),2)
avg_sat_fats = round(sum(sat_fats.Amounts)/len(sat_fats.Amounts),2)
avg_mono_fats = round(sum(mono_fats.Amounts)/len(mono_fats.Amounts),2)
avg_poly_fats = round(sum(poly_fats.Amounts)/len(poly_fats.Amounts),2)

# Created a Python dictionary that holds all the values.

fats_dict = {'Total Fat': avg_all_fats, 'Saturated Fats': avg_sat_fats, 'Monounsaturated Fats': avg_mono_fats, 'Polyunsaturated Fats': avg_poly_fats, 'Trans Fats' : avg_trans_fats, 'Total Calories':  avg_tot_cal}

# Created a new dataframe from those values:

new_df = pd.DataFrame(fats_dict, index=[0])

# ---------------------------------------------------------------

# Created a functional dropdown for each type of fat, [straight from the template.](https://github.com/Coding-with-Adam/Dash-by-Plotly/blob/master/Dash_Interactive_Graphs/pie.py)

layout = html.Div([
     html.Div([
         html.Label(['Fat Ratios to Total Calories']),
         dcc.Dropdown(
             id='my_dropdown',
             options=[
             {'label': 'Total Fat', 'value': 'Total Fat'},
             {'label': 'Saturated Fats', 'value': 'Saturated Fats'},
             {'label': 'Monounsaturated Fats', 'value': 'Monounsaturated Fats'},
             {'label': 'Polyunsaturated Fats', 'value': 'Polyunsaturated Fats'},
             {'label': 'Trans Fats', 'value': 'Trans Fats'}            
             ],
             value='Total Fat',
             multi=False,
             clearable=False,
             style={"width": "50%", 'font-size': 14, 'border': '1px solid black', 'align': 'left', 'color': 'black'}
         ),
     ]),
     html.Hr(),
     html.Div([
         dcc.Graph(id='the_graph')
     ]),

 ])

# ---------------------------------------------------------------

# Created a callback that takes dropdown values as input and changes the pie chart with the output:

@callback(
     Output(component_id='the_graph', component_property='figure'),
     Input(component_id='my_dropdown', component_property='value')
 )

**# This is the problem. The function takes the new dataframe and the dropdown selection chosen by the user and returns the corresponding value, but there is not a way to display the ratio of that percentage to the total calories.** 


def update_graph(my_dropdown):
    dff = 
    
    piechart=px.pie(
            data_frame=dff,
            names=my_dropdown,
            hole=.3,
            )

    return (piechart)


if __name__ == '__main__':
    app.run_server(debug=True)

Hi @robertpfaff,

The issue is mostly related to the dff format, which is wide in your example and should be long. Try something like this:

fats_dict = {
    'Saturated Fats': avg_sat_fats, 
    'Monounsaturated Fats': avg_mono_fats, 
    'Polyunsaturated Fats': avg_poly_fats, 
    'Trans Fats' : avg_trans_fats, 
}

pre_df_dict = {
    "fat_type": [k for k,v in fats_dict.items()],
    "value": [k for k,v in fats_dict.items()]
}

df = pd.DataFrame.from_dict(pre_df_dict)

px.pie(df, values="value", names="fat_type")

(I excluded the total and calories from the dict, as they are not comparable to the rest)-.

1 Like

Thank you. Apparently, I was too “brain dead” last night to finish writing the question!

I never would have thought pie charts could stump me. Pie charts! Would you mind looking at this code one more time when you have the chance? I promise not to ask thrice. I just don’t know why I cannot make it work.

It must be something simple and I just cannot see it.

Many thanks.

My dataset looks like this:

DF:                 fat_type                 value
0                    Saturated Fats        Saturated Fats
1                    Monounsaturated Fats  Monounsaturated Fats
2                    Polyunsaturated Fats  Polyunsaturated Fats
3                   Trans Fats            Trans Fats

My code looks like this:

dash.register_page(__name__, external_stylesheets=[dbc.themes.SUPERHERO])

df = pd.read_csv("final_charts_data.csv")
dff = pd.DataFrame.from_dict(df)

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

trans_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Trans Fats'))]
sat_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Saturated Fat'))]
mono_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Monounsaturated Fats'))]
poly_fats = df.loc[((df['Units'] == 'Percentage') & (df['Nutrients'] == 'Polyunsaturated Fats'))]

avg_mono_fats = round(sum(mono_fats.Amounts)/len(mono_fats.Amounts),4)
avg_poly_fats = round(sum(poly_fats.Amounts)/len(poly_fats.Amounts),4)
avg_sat_fats = round(sum(sat_fats.Amounts)/len(sat_fats.Amounts),4)
avg_trans_fats = round(sum(trans_fats.Amounts)/len(trans_fats.Amounts),4)

fats_dict = {
    'Saturated Fats': avg_sat_fats, 
    'Monounsaturated Fats': avg_mono_fats, 
    'Polyunsaturated Fats': avg_poly_fats, 
    'Trans Fats' : avg_trans_fats, 
}

pre_df_dict = {
    "fat_type": [k for k,v in fats_dict.items()],
    "value": [k for k,v in fats_dict.items()]
}

df = pd.DataFrame.from_dict(pre_df_dict)

layout = dbc.Container([
    dcc.Dropdown(
        id='the-dropdown',
        value='Saturated Fats',
        options=[{'value': x, 'label': x}
                 for x in ['Saturated Fats', 'Monounsaturated Fats', 'Polyunsaturated Fats', 'Trans Fats']],
        clearable=False,
        style={'width': '50%'}
    ),
    dcc.Graph(id="pie-chart"),
], fluid=True)

@callback(
    Output("pie-chart", "figure"),
    Input("the-dropdown", "value"))

def create_piechart(value):
    px.pie(df, values="value")

if __name__ == '__main__':
    app.run_server(debug=True)

I would expect this to raise an error, as df is already a dataframe and not a dictionary. This could be the problem.

Which IDE do you use for development? I think you can benefit from checking out a debugger to inspect the errors. If it is vscode, I can give you some tips on how I use it.