Plotly dash app data not loading on render website

Hi all,

This is my first post on here, I am having trouble with my app so any help would be greatly appreciated. I think I posted all the info needed, if you need any additional information ill get it posted as soon as I can, Thanks!

app setup:
The app is from a pokemon dataset and there are 2 dropdown menus for type1 and type2, where type 2 is updated after selection on type 1 and the plot defaults to plotting all the data. There are 3 plots, 1 scatterplot of attack/defense, 1 histogram of hp and a pie chart of the proportion of the selection that are legendary pokemon.

summary:
I deployed a plotly dash app on render, however the data is not being uploaded into the plots. I am using the exact code that i built the apps on both Pycharm and Jupyter notebooks and the app works great, but not on the website. The dropdown selections contain the labels, but the plots do not update when a selection is made.

error:
Apr 13 12:35:11 PM pie_chart = px.pie(legendary_counts, values=legendary_counts.legendary, names=legendary_counts.index)
Apr 13 12:35:11 PM File “/opt/render/project/src/.venv/lib/python3.10/site-packages/pandas/core/generic.py”, line 5989, in getattr
Apr 13 12:35:11 PM return object.getattribute(self, name)
Apr 13 12:35:11 PM AttributeError: ‘DataFrame’ object has no attribute ‘legendary’

Is it a problem with the pie chart? When I went back through the code, the dataframe does have ‘legendary’. Ive been chasing this error for days and havent been able to resolve the error.

app url: https://pokemon-stats-app.onrender.com/

code:

data management and manipulation
import pandas as pd
import numpy as np

matplotlib and seaborn

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import seaborn as sns
#plotly
import plotly as py
import plotly.express as px
import plotly.graph_objects as go
import dash
from dash import dcc
from dash.dependencies import Input, Output
from dash import html

create dash app

app = dash.Dash(name)

#create server name used for dash-app
server = app.server

#import dataset
file = pd.read_csv(‘https://raw.githubusercontent.com/Dave-314/Pokemon-Stats-Dash-App/main/Pokemon.csv’)
pokedata = pd.DataFrame(file)

change NaN to read ‘None’ because not all pokemon have 2 types

pokedata[‘Type 2’].fillna(‘None’, inplace=True)

change ‘#’ column name to ‘Number’

pokedata.rename(columns={‘#’: ‘number’}, inplace=True)
#column names: remove spaces, replace ‘.’ with underscore, convert to all lower case
pokedata.columns = pokedata.columns.str.replace(’ ‘, ‘’, regex=False)
pokedata.columns = pokedata.columns.str.replace(’.', ‘_’, regex=False)
pokedata.columns = pokedata.columns.str.lower()

create dash app with multiple chained callbacks to Pokemon Type1

get unique pokemon type1 and sort alphabetically to input to dropdown options

pokesorted = pokedata.sort_values([‘type1’, ‘name’], ascending=True)
unique_type1 = pokedata[‘type1’].unique()
unique_type1.sort()

create dictionary for dash dropdown labels and values

type1_dd_list = [{‘label’: x, ‘value’: x} for x in unique_type1]

create app layout

app.layout = html.Div([

overall app title

html.H1(‘Pokemon Stats’),
html.Div(
# divide app into 2 inline-blocks

   children=[
       html.Div(
           # first inline-block
           children=[
               # type 1 dropdown scatter plot
               html.H2('Select Pokemon Type'),
               html.Div(
                   children=[
                       # first dropdown for type1
                       html.H3('First type:'),
                       dcc.Dropdown(id='type1_dd',
                                    options=type1_dd_list,
                                    style={'width': '200px', 'margin': '0 auto'}
                                    )],
                   # format type1 dropdown as inline block with type2 dropdown
                   style={'display': 'inline-block', 'align': 'center'}
               ),
               html.Div(
                   children=[
                       # second dropdown for type2
                       html.H3('Optional second type: '),
                       dcc.Dropdown(id='type2_dd',
                                    style={'width': '200px', 'margin': '0 auto'}
                                    )
                   ],
                   # format type2 dropdown as inline block with type1 dropdown
                   style={'display': 'inline-block', 'align': 'center', 'margin': '50px'}
               ),
               # scatter plot for type1 and/or type2
               dcc.Graph(id='type_scatter')
           ],
           # format right side inline block
           style={'display': 'inline-block', 'width': '700px', 'height': '500px', 'text-align': 'center'}
       ),
       html.Div(
           # second inline-block
           children=[
               # top plot as a histogram
               html.H2('Histogram of Hit Points (hp)'),
               dcc.Graph(id='histogram'),
               # bottom plot as pie chart
               html.H2('Percentage Legendary'),
               dcc.Graph(id='pie_chart')
           ],
           # format left inline block
           style={'display': 'inline-block', 'width': '700px', 'height': '10px',
                  'vertical-align': 'top', 'text-align': 'center'}
       ),
   ]

)
],

format overall layout of app

style={‘text-align’: ‘center’})

create callback to update type2 dropdown from ‘type1_dd’

@app.callback(

options is used for output of the chained dropdown for type2

Output(component_id=‘type2_dd’, component_property=‘options’),
Input(component_id=‘type1_dd’, component_property=‘value’)
)

function to fiter and update scatter plot from type1_dd

def update_type2_dd(type2_dd):
poke = pokesorted.copy(deep=True)

find combinations of type1 and type2

type1_type2 = poke[[‘type1’, ‘type2’]].drop_duplicates()
relevant_type2_dd_options = type1_type2[type1_type2[‘type1’] == type2_dd][‘type2’].values.tolist()

create type2_dd dictionary of labels and values

formatted_relevant_type2_dd_options = [{‘label’: x, ‘value’: x} for x in relevant_type2_dd_options]
return formatted_relevant_type2_dd_options

create callback for scatterpolot to update with type1 and filter when selecting type2

all 3 plots will update when type1 is selected and will update again when type2 is selected

@app.callback(
[Output(component_id=‘type_scatter’, component_property=‘figure’),
Output(component_id=‘histogram’, component_property=‘figure’),
Output(component_id=‘pie_chart’, component_property=‘figure’)],
[Input(component_id=‘type1_dd’, component_property=‘value’),
Input(component_id=‘type2_dd’, component_property=‘value’)]
)
def update_scatter_type2(type1_dd, type2_dd):
type2_title = ‘All’
poke = pokesorted.copy(deep=True)

if type1_dd:
type1_title = type1_dd
poke = poke[poke[‘type1’] == type1_dd]

if type2 is not selected do not filter the dataset further

if type2_dd:
type2_title = type2_dd
poke = poke[poke[‘type2’] == type2_dd]

scatter plot

type_scatter = px.scatter(data_frame=poke, x=poke.attack, y=poke.defense,
custom_data=[poke.name],
hover_data=[poke.name],
color=poke.legendary)
type_scatter.update_xaxes(range=[0, 200])
type_scatter.update_yaxes(range=[0, 250])

histogram

histogram = px.histogram(poke, x=‘hp’, nbins=20)
histogram.update_xaxes(range=[0, 250])

pie chart

for legendary variable: get value counts, convert to dataframe and rename index

legendary_counts = pd.DataFrame(poke[‘legendary’].value_counts()).rename(index={False: ‘Not >Legendary’,
True: ‘Legendary’})
pie_chart = px.pie(legendary_counts, values=legendary_counts.legendary, >names=legendary_counts.index)
return type_scatter, histogram, pie_chart

if name == ‘main’:
app.run_server(debug=True)

I’ve been looking into it further and when on the render app I right clicked then clicked on inspect. I saw there was an error

‘Failed to load resource: the server responded with a status of 500 ()’
and the message was

‘message: there was an error updating…type_scatter.figure…histogram.figure…pie_chart.figure…’, html: ‘<!doctype html>\n\n500 Internal…ded or there is an error in the application.

\n’}html: "<!doctype html>\n<html la’

The app is able to access the data in order to utilize the 2 dropdown selections but unable to update the plot. I cant figure this out because it works fine from PyCharm or Jupyter notebook.

Thanks

Hi,

General code debugging is beyond the scope of Render support, but maybe another member of the community will be able to offer assistance.

A message such as Failed to load resource: the server responded with a status of 500 on the front-end will usually be accompanied by an error/stacktace in your Render service logs.

From what you’ve provided, I think you need to take a look at:

legendary_counts = pd.DataFrame(poke['legendary'].value_counts()).rename(index={False: 'Not Legendary', True: 'Legendary'})pie_chart = px.pie(legendary_counts, values=legendary_counts.legendary, names=legendary_counts.index)

I’m not familiar with Python/Plotly, but this is likely not producing the dataset you think it is. It might help to add some debug code to output the result of legendary_counts to see what it contains, pprint maybe? And the pie values would be the count wouldn’t they?

Good luck in your debugging!

Alan

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.