Updating a pre-rendered graph with Radio Buttons


#1

Hey all,

First, I just wanted to say the amount of community support around this module is fantastic and has made learning how to use Dash wonderful. I’m relatively novice with python, dash, and data manipulation entirely, and I’m stuck with a bit of a problem. What I have is a multi-page app where I am generating graphs on demand via a dropdown menu. Some of these graphs have radio buttons attached, and these theoretically would be hiding traces or otherwise modifying the graph. I am entirely lost as to how to implement this, as I’m not very familiar with the html markup nor the data structures that Div implies, so accessing an embedded attribute is difficult for me if there are multiple in a Div.

What I want to do immediately is show/hide a set of traces per radio button clicked. I have a function that is called upon a dropdown selection, and the traces are hidden/shown via the ‘visible’ attribute.

Here is what I have so far, and any help would be greatly appreciated. I am trying to understand this conceptually.

def total_user(df):
	filtered = unique_session(df)
	x = filtered.index
	xi = arange(0, len(x))
	y1 = filtered['totalvisits']
	y2 = filtered['uniquevisits']

	slope1, intercept1, r1, p1, std_err1 = stats.linregress(xi, y1)
	line1 = slope1 * xi + intercept1
	slope2, intercept2, r2, p2, std_err2 = stats.linregress(xi, y2)
	line2 = slope2 * xi + intercept2

	trace1 = {
		'x': x,
		'y': y1,
		'type': 'bar',
		'name': 'Total Sessions',
		'marker': {
			'color': 'rgb(158,202,225)',
			'line': {
				'color': 'rgb(8,48,107)',
				'width': 1.5
			}
		},
		'opacity': 0.6
	}

	trace2 = {
		'x': x,
		'y': y2,
		'type': 'bar',
		'name': 'Unique Sessions',
		'textposition': 'auto',
		'marker': {
			'color': 'rgb(245,16,0)',
			'line': {
				'color': 'rgb(8,48,107)',
				'width': 1.5
			}
		},
		'opacity': 0.6

	}

	linear_total = {
		'x': x,
		'y': line1,
		'mode': 'lines',
		'marker': {
			'size': 10,
			'color': 'rgb(205,30,30)',
			'line': {
				'width': 2,
				'color': 'rgb(0, 0, 0)'
			}
		},
		'opacity': 0.6,
		'hoverinfo': '',
		'visible': True
	}

	linear_unique = {
		'x': x,
		'y': line2,
		'mode': 'lines',
		'marker': {
			'size': '10',
			'color': 'rgb(205,30,30)',
			'line': {
				'width': 2,
				'color': 'rgb(0, 0, 0)'
			}
		},
		'opacity': 0.6,
		'hoverinfo': '',
		'visible': True
	}

	return html.Div([
		dcc.RadioItems(
			id='linear_fit',
			options=[{'label': i, 'value': i} for i in ['Total', 'Unique', 'Both', 'None']],
			value='Total',
			labelStyle={'display': 'inline-block'},
			style={'display': 'none'}
		),
		dcc.Graph(
			id='total_session',
			figure={
				'data': [trace1, trace2, linear_unique, linear_total],
				'layout': {
					'title': 'Total and Unique Session per month',
					'margin': {'b': 50, 'r': 30, 'l': 60, 't': 60},
					'paper_bgcolor': 'rgb(240, 240, 240)',
					'plot_bgcolor': 'rgb(233,233,233)',
					'dragmode': 'x',
					'legend': {'x': 1, 'y': 1},
					'barmode': 'overlay',
					'font': {
						'color': "#444",
						'familY': "Georgia, serif",
						'size': 12
					}
				}
			}
		)
	])

Then, here is the callback to populate the graphs:

@app.callback(
	dash.dependencies.Output('graphs', 'children'),
	[dash.dependencies.Input('graph-selector', 'value'),
	 dash.dependencies.Input('cache', 'children')]
)
def gen_graph(graph_value, cache):
	if cache is None:
		raise PreventUpdate
	graphs = []
	temp = unpack_json(cache)
	for k in graph_value:
		if k == 'total_unique':
			graphs.append(total_user(temp))
		elif k == 'percent':
			graphs.append(test(temp))
	return graphs

Now, I have absolutely no idea how to update those ‘visible’ fields per dropdown. All I have is this:

@app.callback(
	dash.dependencies.Output('total_session', 'data'),
	[dash.dependencies.Input('linear_fit', 'value')]
)
def show_regr_line(value):
	if value == 'Total':
		pass
	elif value == 'Unique':
		pass
	elif value == 'Both':
		pass
	elif value == 'None':
		pass

#2

I am not sure I fully understand what you want to do, but to hide or show traces on the same graph can be done by changing the opacity of the curve. You can also set the data to [], but this only works if you do it once (then the ‘data’ attribute of your graph will have one empty data set, so you would need to reset it to the values it had before.

Let me know if I was totally off answering your question :slight_smile:

@app.callback(
   dash.dependencies.Output('total_session', 'figure'),
   [dash.dependencies.Input('linear_fit', 'value')],
   [dash.dependencies.State('total_session', 'figure')]
)
def show_regr_line(value, fig):
   data = fig['data']

   if value == 'Total':
       data[2]['opacity'] = 0.6
       data[3]['opacity'] = 0 #hides it on the graph, but still there in the legends
       data[3] = [] #completely erases it
   elif value == 'Unique':
       data[2]['opacity'] = 0
       data[3]['opacity'] = 0.6
   elif value == 'Both':
       data[2]['opacity'] = 0.6
       data[3]['opacity'] = 0.6
   elif value == 'None':
       data[2]['opacity'] = 0
       data[3]['opacity'] = 0

   fig['data'] = data
   return fig