Can I align a Sunburst label in the midpoint of the wedge?

Hi,

I am creating a sunburst chart in Python using Plotly Express, but the inside text labels are not centred in the ‘wedges’.

It seems that the label on the left most wedge is always set to ‘9 o’clock’, and on the right at ‘3 o’clock’.

Is there a way to adjust it so the label is in the centre of the wedge, but still in a radial orientation so that it is angled radially. As you can see, almost all of the other labels are oriented correctly.

Current format, where the tags (e.g., Packaging 7) are not in the center of the wedge:

I currently use Plotly express but I can also use Plotly graph objects.

The current code is as follows:

mport pandas as pd
import plotly.express as px
import plotly.io as io
import textwrap

wrap_width = 25
def customwrap(s,width=wrap_width): #Function responsible for wrapping text for the captions
    return "<br>".join(textwrap.wrap(s,width=width))

io.renderers.default='browser'

scope = ['Scope 1','Scope 1', 'Scope 2', 'Scope 2', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3',
 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3', 'Scope 3',
 'Scope 3', 'Scope 3', 'Scope 3']

component = ['Diesel (company vehicles)', 'Petrol (company vehicles)', 'Electricity for<br>appliances', 'Other Scope 2', 'Fuel- and energy-related<br>activities (FERA)', 'Upstream transportation<br>in operations', 
             'Other Scope 3', 'Other Scope 3','Employee commuting', 'Downstream transportation<br>and distribution', 'Use of sold products<br>(including indirect use)', 'End-of-life treatment of<br>sold products',
 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services',
 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services',
 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services', 'Purchased goods &<br>services']

other1 = [None, None, None, 'Other electricity usage', None, None, 'Waste generated in operations', 'Business travel', None, None, None, None, 'External services', 'Other', 'Component 3', 'Other', 'Other', 'Other', 'Other', 'Other',
 'Other', 'Other', 'Other', 'Other', 'Other', 'Other', 'Other', 'Packaging 1', 'Other', 'Other', 'Other', 'Other', 'Packaging 6', 'Other', 'Packaging 8']

other2 = [None, None, None, None, None, None, None, None, None, None, None, None, None, 'Component 2', None, 'Component 4', 'Other', 'Other', 'Other', 'Other', 'Other', 'Other', 'Other', 'Other', 'Component 18',
 'Other', 'Other', None, 'Packaging 2', 'Packaging 3', 'Packaging 4', 'Other', None, 'Packaging 7', None]

other3 = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
 'Component 5', 'Component 6', 'Component 8', 'Component 10', 'Component 11', 'Component 15', 'Component 16', 'Component 17',
 None, 'Component 19', 'Component 20', None, None, None, None, 'Packaging 5', None, None, None]

my_val = [764.7025037682, 922.1573873343998, 1957.1932799999997, 140.7, 1207.8232972546991, 2281.8435614470854, 515.076626462584, 29.182320239999992,
 1121.2985380110642, 1719.9014327173065, 3775.035531264989, 1070.6572813460293, 1674.5794717430463, 30.810666030133756, 422.10395987932935, 56.39659050619138,
 6.3586116808006095, 4.512960708715524, 1.9694367644506894, 1.3722071788772845, 2.7747701218460326, 0.2114258879480555, 0.9394050913579317, 0.04218689368287673,
 45.71662577815401, 8.498568925771194, 0.40354149057007305, 1719.5614117487207, 58.05899316001125, 69.89255424737141, 17.751589750845255, 7.775786234929822,
 3190.0304754954027, 134.42401811928045, 792.7971957632528]

df = pd.DataFrame(list(zip(scope,component,other1,other2,other3,my_val)),
                       columns = ['Scope','Component','Other_label','Layer_2','Layer_3','tCO2e'])


g1 = df.Scope.map(customwrap) #Wrapping the text in the sunburst slices
g2 = df.Component.map(customwrap) #Wrapping the text in the sunburst slices

burst_df = pd.DataFrame(
    dict(scope_layer=g1, component_layer=g2, other_layer=df.Other_label, layer_2=df.Layer_2, layer_3=df.Layer_3, my_values=df.tCO2e))

burst_df = burst_df.drop(burst_df[burst_df.my_values == 0].index) #Drop any rows where the value is zero. They do not show up anyway and can cause problems.

fig = px.sunburst(burst_df, path=['scope_layer','component_layer','other_layer','layer_2','layer_3'], values='my_values',
                  maxdepth=2, title='Carbon footprint of 2021')

fig.update_traces(hovertemplate="%{label} <br>%{value:.1f} tCO\u2082e <extra></extra>",insidetextorientation='radial', rotation=90)

fig.show()

https://plotly.com/python/sunburst-charts/
In all the example provided by Plotly, the label is always in the center of the wedges.

Hi AbdelAnlah,

Thank you for your reply. You are correct, but the majority of those do not use textorientation = ‘radial’, which is something I need as I feel it looks far better than the automatic design.

One example does use ‘radial’, but the nature of the data (small wedges) makes it not face the same issue I do.

I will add reproducible data to my question.

Thank you

It looks like there is an issue with the centering of the inside text labels in your sunburst chart. To ensure that the labels are properly centered within the wedges, you can try using the ‘insidetextorientation’ parameter in Plotly Express. Set it to ‘radial’ to keep the Classic radial orientation of the labels while centering them within the wedges. Here’s how you can modify your code:

pythonCopy code

import pandas as pd
import plotly.express as px
import plotly.io as io
import textwrap

wrap_width = 25
def customwrap(s, width=wrap_width): #Function responsible for wrapping text for the captions
    return "<br>".join(textwrap.wrap(s, width=width))

io.renderers.default = 'browser'

# Your data goes here

fig = px.sunburst(df, path=['Scope', 'Component', 'Other1', 'Other2'],
                  values='values', maxdepth=2,
                  custom_data=[df['labels']],
                  branchvalues='total',
                  labels={'labels': 'Caption'},
                  hover_data={'values': False},
                  insidetextorientation='radial')  # Add this parameter to center the text

# Rest of your code and layout settings

fig.show()

By setting ‘insidetextorientation’ to ‘radial’, the text labels should now be centered within the wedges while maintaining their radial orientation. Give it a try and see if it resolves the issue with the labels’ positioning.

Thank you for your reply and apologies for the delayed response.

I am trying to work with ‘radial’, but the issue I face is that it is not always centred in the wedge, usually at the 90 and 270 degrees positions (see screenshot). I annotated where the text should be instead.

Do you have any ideas?

Thank you