I am having issues adding an annotation in the center of each donut in a facet. I can seem to get the annotation centered in one facet, but not automatically in the others. In the example below, I just have one row, but I also have the same issue when having multiple rows. Is there a way to do this or another approach I should be taking?
import pandas as pd
import psycopg2
from sqlalchemy import create_engine, URL
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
from plotly import tools
import plotly.offline as pyo
import dash
year = ['2021', '2022', '2023', '2021', '2022', '2023', '2021', '2022', '2023']
answer_cat = ['Promoters', 'Promoters', 'Promoters', 'Passives', 'Passives', 'Passives', 'Detractors', 'Detractors', 'Detractors']
unique_cnt = [778, 871, 432, 407, 476, 324, 126, 147, 104]
dict_d = {'year': year, 'answer_cat': answer_cat, 'unique_cnt': unique_cnt}
df = pd.DataFrame(dict_d)
fig = px.pie(df,
values='unique_cnt',
names='answer_cat',
facet_col='year',
color='answer_cat',
hole=.55,
category_orders={'year': ['2021', '2022', '2023'],
'answer_cat': ['Promoters', 'Passives', 'Detractors']
},
color_discrete_map={'Promoters':'lightgreen',
'Passives':'lightgrey',
'Detractors':'#FF474C'},
height=400, width=1800
)
fig.update_traces(hoverinfo='label+percent', texttemplate='%{percent}', textfont_size=14, textposition='outside',
marker=dict( line=dict(color='#FFFFFF', width=2)))
fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]) )
fig.update_layout(legend=dict(
orientation="h",
entrywidth=70,
yanchor="bottom",
y=-.25,
xanchor="center",
x=.5
))
# Add total value in the center of each subplot's donut hole
total_subplots = len(['2021', '2022', '2023'])
subplot_width = 0.33125
for i, year_val in enumerate(['2021', '2022', '2023']):
total_value = df[df['year'] == year_val]['unique_cnt'].sum()
nps_promoters = df[(df['year'] == year_val) & (df['answer_cat'] == 'Promoters')]['unique_cnt'].sum()
nps_detractors = df[(df['year'] == year_val) & (df['answer_cat'] == 'Detractors')]['unique_cnt'].sum()
nps_score = (((nps_promoters)/(total_value) - (nps_detractors)/(total_value) ) * 100).round(1)
text_str = '<span style="font-size: 16px;"><b>' + str(nps_score) + '</b></span><br><span style="font-size: 12px;">(' + str(total_value) + ')</span>'
# Calculate the x position based on the subplot width and index
x_position = (i + 0.5125) * subplot_width
# x_position = (i * subplot_width) + (subplot_width / 2)
# x_position = (i * subplot_width) + (subplot_width / 2) + (subplot_width / (2 * total_subplots)) - (0.5 * subplot_width)
# x_position = (i * subplot_width) + (subplot_width / 2) + (subplot_width / (2 * total_subplots)) - (subplot_width / 2)
# x_position = (i * subplot_width) + (subplot_width / 2) + (subplot_width / (2 * total_subplots))
# x_position = (i * subplot_width) + (subplot_width / 2) + (subplot_width / total_subplots)
fig.add_annotation(
xref="paper",
yref="paper",
x=x_position,
y=0.5,
text=(text_str),
showarrow=False
)
fig.show()```
![NPS - Center Issue|690x153](upload://yoGnEzJgWPelKpJ6S4fms71H0pw.png)