✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

Density Plots - Smoother, More Conventional Tails

I’m developing ridgeline density plots as part of an interactive visual (http://statscope.herokuapp.com/). It seems that Plotly defaults to cutting off the tails of density plots very suddenly to accurately represent the data. Like this:

But I prefer that my density plots have more conventional tails as seen here:

Can anyone recommend how to modify my density plots to be more conventional in their depiction of the tails?

How are you creating these plots? You might want to check out the violin trace type, I think there is an option to make it “one-sided”

I believe we are using distplot (https://plot.ly/python/distplot/). This seemed to display just the density curves, so we shaded the region under the curve. Previously, we attempted to simply cut the violin plot in half and use that for density ridgeline plots, but we found that the resulting plots were too small and did not make full use of the plotting space. As a result, we reverted to using dist_plot and “subplots” to stack the curves vertically. Now, we are trying to smooth out the tails and perform other minor aesthetic edits to make them look more pleasing and similar to the temperature plot I embedded above.

The code from my team is below.

if graphType == ‘Density Plot’:

	for i,trace in enumerate(traceValues):
		if len(trace) < 2:
			del traceValues[i] # can't plot the density of a single variable without errors
	
	if tuningSliderValue is None or tuningSliderValue < 0 or tuningSliderValue >= len(DENSITY_CURVE_TYPES):
		tuningSliderValue = 0
	try:
		graphFigure = ff.create_distplot(
			traceValues, traceNames,
			show_hist=False, show_rug=False, curve_type=DENSITY_CURVE_TYPES[int(tuningSliderValue)],
			)
	except Exception as e:
		layout['title'] = "Error: " + str(e) # show error message in graph title
		return [dcc.Graph(id=GRAPH_ID, figure=go.Figure(layout=layout), config=graphConfig)] # empty graph

	if showDataBoolean:
		for i,trace in enumerate(graphFigure.data):
			trace['fill'] = 'tozeroy'
			trace['marker']['color'] = PLOTLY_DEFAULT_COLORS[i % len(PLOTLY_DEFAULT_COLORS)]
	else:
		for trace in graphFigure.data:
			trace['marker']['color'] = 'rgba(0,0,0,0)'
			trace['fillcolor'] = 'rgba(0,0,0,0)'
	
	ridgelineFigure = plotlyTools.make_subplots(
		rows=len(traceValues),
		cols=1,
		specs=[[{}] for i in range(len(traceValues))],
		shared_xaxes=True, 
		shared_yaxes=True,
		vertical_spacing=0,
		)
	for i,trace in enumerate(reversed(graphFigure.data)):
		ridgelineFigure.append_trace(trace, i+1, 1)

	layout['xaxis']['title'] = str(chosenDataFields)[1:-1].replace("'","")
	layout['yaxis']['hoverformat'] = '.3f'
	layout['yaxis']['showticklabels'] = False
	layout['yaxis']['ticks'] = ''
	layout['yaxis']['title'] = ''
	ridgeLayout = ridgelineFigure['layout']
	for key,value in ridgeLayout.items():
		if len(key) >= 5 and (key[:5] == "xaxis" or key[:5] == "yaxis"):
			for k,v in layout[key[:5]].items():
				value[k] = v
	layout['annotations'] = [
		dict(
			xref='paper',
			xanchor='right',
			x=-0.01,
			yref='y'+(str(i+1) if (i > 0) else ''),
			# possible speed improvement: if graphFigure.data[len(traceNames)-i-1]['y'] is sorted, can use [-1] instead of max()
			y=0.5*max(graphFigure.data[len(traceNames)-i-1]['y']), 
			text=traceNames[len(traceNames)-i-1],
			font=dict(size=14, family='Arial'),
			showarrow=False,
			)
		for i in range(len(traceNames))
		]
	del layout['xaxis']
	del layout['yaxis']
	ridgeLayout.update(layout)
	return [
		dcc.Graph(id=GRAPH_ID, figure=ridgelineFigure, config=graphConfig)
		]

Cross-linking Ridgeline/Joy Plots in Dash (Automatic)