Plotly: How to handle varying text sizes in a stacked funnel plot?

Viewed 727

I'm attempting to produce a stacked funnel plot of activities. The labels are not appearing as expected on the plot.

First my code:

import pandas as pd
import plotly.express as px

stages = ["Initial Landing", "Step 2", "Step 3", "Added to cart", "Purchased"]
regiona_plotly = pd.DataFrame(dict(number=[10866,10543,1067,1032,108], stage=stages))
regionb_plotly = pd.DataFrame(dict(number=[10650,10432,1076,1036,1012], stage=stages))
regiona_plotly['region'] = "Region A"
regionb_plotly['region'] = "Region B"
df = pd.concat([regiona_plotly, regionb_plotly], axis=0)
fig = px.funnel(df, x='number', y='stage', color='region')
fig.update_traces(textposition='auto')
fig.update_layout(autosize=True)
fig.write_image("region_funnel.png")

(Lifted almost entirely from plotly documents)

This code produces an image like so: Plotly - Auto Text Position

Notice that on "Step 3", "Added to cart", and "Purchased" the region A text is scaled very small and inside the bar, but Region B is outside.

I tried updating this line:

fig.update_traces(textposition='outside')

But, with this, I get both values overlapping on the Region B side of the funnel. Also, the text goes outside of the plot on the upper bands.

Plotly - Outside Text Position

How can I get text to be the same size and either be within the bar if it fits at the size or outside and on the correct side, if it doesn't?

1 Answers

Short answer:

This seems to be a bug. If what you need is a .png image of your figure, run:

import plotly
plotly.offline.plot(fig, filename='funnel.html')

And then produce a .png version using the user interface camera icon:

enter image description here

Result:

enter image description here


The details:

This is a strange one. And quite possibly a bug that would be of interest to the plotly community forum. I have a work-around though. Assuming that what you would in fact like to end up with here is a .png image file of your plot.

If you run your exact code in JupyterLab, but exchange the line fig.write_image("region_funnel.png") with just fig.show(), you'll get this:

enter image description here

No small text there! And if I understand correctly, a figure without varying text size would be a satisfactory solution? But fig.show() creates a html object, and not a .png image. So I tested the available output options for fig.write_image() which are:

  • 'png'
  • 'jpg' or 'jpeg'
  • 'webp'
  • 'svg'
  • 'pdf'
  • 'eps' (Requires the poppler library to be installed)

I ruled out webp and eps as viable solutions and tested the rest of them. And each and every one produced the same undeseried varying text sizes. Even producing a figure using fig.show() in JupyterLab and then manually downloading a file using the user interface camera icon produced the very same results even though the html version looked fine.

But if you run:

import plotly
plotly.offline.plot(fig, filename='funnel.html')

And then download a .png version you'll get this:

enter image description here

Which should be a viable option for you if I understand correctly. Admittedly, this is far from a perfect answer, but I hope you'll find it useful all the same.

Related