Error handling with graphs

I’m creating an interactive graph that display pay rate data. Some occupations though have their salary data represented as an (asterisk) i.e:* , when it is not reported.

This doesn’t crash the program, but it also doesn’t change the charts which means that the previous occupation data is still showing. Below is what the command line spits out when I encounter this issue:

"${:.2f}".format(queryResult.H_MEAN.values[0]),
ValueError: Unknown format code 'f' for object of type 'str'

How can I catch these exceptions and make the application render a blank bar for the missing value, and even better, also have a footnote appear below the graph?

Below is a snippet of the relevant code:

Thanks!

def update_pay_rate_graph(occ_selection):
	queryResult = df[df['OCC_CODE'] == occ_selection]
	return {
		'data': [
				go.Bar(
					x=['mean', '25th', 'median','75th'],
					y=[
						queryResult.H_MEAN.values[0], 
						queryResult.H_PCT25.values[0], 
						queryResult.H_MEDIAN.values[0],
						queryResult.H_PCT75.values[0]
						
						],
					textfont={'color':"#FFFFFF",'size': 24},
					
						text = [
							"${:.2f}".format(queryResult.H_MEAN.values[0]), 
							"${:.2f}".format(queryResult.H_PCT25.values[0]), 
							"${:.2f}".format(queryResult.H_MEDIAN.values[0]),
							"${:.2f}".format(queryResult.H_PCT75.values[0])
							],
					textposition = 'auto'
				)	
			],
			'layout': go.Layout(
				title = 'Hourly rate for {}'.format(queryResult.OCC_TITLE.values[0])
			),	
	}

You’ll have to do some validation of the input up front before creating the figure data to return. Either explicitly eg:

if occ_selection == '*':
    # do stuff

Or through exception handling:

try:
  "${:.2f}".format(queryResult.H_MEAN.values[0])
except ValueErr as e:
  # do stuff

Either way, you’ll need to do this validation up front before creating the Figure dictionary to return. This way you can detect problematic inputs and define default values for the corresponding elements in the y and text lists.

That’s what I was going to do, but it seemed a bit verbose so I wanted to see if there was a more elegant solution. As for the footnotes, is there any way I can edit an HTML element via the app.callback decorator? That seems like one way to note the missing data.

The magic of Dash all happens in integrating your Python callbacks with a reactive front-end (defined in Python also). But you still have to write the Python callbacks. To me, this is also a strength, as it means I have complete freedom to prepare the returned data in whatever way I want. Automatically working out how invalid input should be handled for your specific use case would be true magic indeed :slight_smile:

You can insert the results of your callback into the HTML of the page by simply targeting the children property of a target element and returning either text or an html Component. The only catch is that you have to target a single element. So you can’t target both the figure property of a Graph element and the children property of an element with an error message. You would have to return an html component that wraps up both a Graph with the new data, and an html component with a message message.

2 Likes

@nedned could you elaborate a little more on:

You would have to return an html component that wraps up both a Graph with the new data, and an html component with a message message.

Are you saying that I would have an app callback with an output of a div? or two app callbacks, one for a figure and another for an html element?

Also, is there documentation on all the outputs that can be used in the app callback decorator function. I know that the guide talks about figures and html elements, but it would be nice to see a thorough list of all possibilities. Maybe @chriddyp has some insight on this as well.

Thanks.

@mbkupfer - I tried to explain this in the section on interactivity in the user guide: Part 2. Basic Callbacks | Dash for Python Documentation | Plotly. Quoting from those docs:

  1. In Dash, the inputs and outputs of our application are simply the properties of a particular component. In this example, our input is the “value” property of the component that has the ID “my-id”. Our output is the “children” property of the component with the ID “my-div”.

Remember how every component was described entirely through its set of keyword arguments? Those properties are important now. With Dash interactivity, we can dynamically update any of those properties through a callback function. Frequently we’ll update the children of a component to display new text or the figure of a dcc.Graph component to display new data, but we could also update the style of a component or even the available options of a dcc.Dropdown component!

1 Like

Ah I see, that make more sense now. Thanks for clarifying!

1 Like