Bar chart text cut off with subplots and fixed height

Hello everyone,
I appear to have an issue with the text of the highest bar in the bar chart in case I place the text outside (on top off) the bar. This happens specifically in case I create it within a subplot and with a defined height. Anybody a clue how to fix this?

# imports
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import pandas as pd
import numpy as np

# data
labels = ['Q4 Act LY','Q1 Act CY','Q2 Act CY','Q3 Act CY','Q4 Act CY']
actual = [36,39,41,36,37]
target = [33,38,38,37,37]

data_dict_people = {'Labels':labels,'Actual':actual,'Target':target}
df_people_graph = pd.DataFrame(data = data_dict_people)

index_labels = ['A', 'B', 'C', 'D', 'E']
nps_data_table = [[81,85,87,87,79],[89,80,73,89,72],[93,91,94,96,94],[85,86,73,86,86],[87,87,84,90,79]]
df_people_table = pd.DataFrame(data = nps_data_table, columns=labels, index=index_labels)

# set up plotly figure
fig = make_subplots(2,2,specs=[[{"type": "xy"},{"type": "xy"}],[{"type": "domain"},{"type": "domain"}]], vertical_spacing=0, horizontal_spacing=0, column_widths=[0.05,0.95])

# add first bar trace at row = 1, col = 2
fig.add_trace(go.Bar(x=df_people_graph['Labels'], y=df_people_graph['Actual'],
                     name='Actual',
                     marker_color = 'grey',
                     opacity=0.4,
                     marker_line_color='grey',
                     marker_line_width=2,
                     text=df_people_graph['Actual'],
                     textfont=dict(color='#ffffff', family='Lato', size=20),
                     textposition='outside'),
              row = 1, col = 2)

# add first scatter trace at row = 1, col = 2
fig.add_trace(go.Scatter(x=df_people_graph['Labels'], 
                        y=df_people_graph['Target'],
                        mode='markers+text+lines' ,
                        line=dict(color='#00E487'), 
                        marker=dict(size=10), 
                        name='Target', 
                        text=df_people_graph['Target'],
                        textfont=dict(color='#ffffff', family='Lato', size=20)),
              row = 1, col = 2)

fig.add_trace(go.Table(header=dict(values=[''], line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30),
                 cells=dict(values=[df_people_table.index],align='left', line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30)),
                 row=2, col=1)
fig.add_trace(go.Table(header=dict(values=df_people_table.columns, line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30),
                 cells=dict(values=df_people_table.values, line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30)),
                 row=2, col=2)

fig.update_xaxes(showgrid=False)
fig.update_yaxes(showgrid=False)
fig.update_layout(yaxis2={'visible': False, 'showticklabels': False})
fig.update_layout(plot_bgcolor="#0E1117",
                    legend=dict(yanchor="top", y=1.1, xanchor="left", x=0.5, orientation='h'),
                    margin= dict(t=0)
                    )
fig.update_layout(height=600, width=1400)
fig.show()

Hi @limartje, increasing the y- axis of the bar chart and increasing the figure height does the trick. Since you are using subplots, I used fig.for_each_yaxis()

This is what I added/changed to your code:

# calculate the maximum y value, add 10%
max_y_axis = max(actual+target) * 1.1

# update yaxis range
fig.for_each_yaxis(lambda x: x.update({'range': [0, max_y_axis]}))

# increase figure height from 600 to 900
fig.update_layout(height=900, width=1400)

Full code:

# imports
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import pandas as pd
import numpy as np

# data
labels = ['Q4 Act LY','Q1 Act CY','Q2 Act CY','Q3 Act CY','Q4 Act CY']
actual = [36,39,41,36,37]
target = [33,38,38,37,37]

data_dict_people = {'Labels':labels,'Actual':actual,'Target':target}
df_people_graph = pd.DataFrame(data = data_dict_people)

index_labels = ['A', 'B', 'C', 'D', 'E']
nps_data_table = [[81,85,87,87,79],[89,80,73,89,72],[93,91,94,96,94],[85,86,73,86,86],[87,87,84,90,79]]
df_people_table = pd.DataFrame(data = nps_data_table, columns=labels, index=index_labels)

# set up plotly figure
fig = make_subplots(2,2,specs=[[{"type": "xy"},{"type": "xy"}],[{"type": "domain"},{"type": "domain"}]], vertical_spacing=0, horizontal_spacing=0, column_widths=[0.05,0.95])

# add first bar trace at row = 1, col = 2
fig.add_trace(go.Bar(x=df_people_graph['Labels'], y=df_people_graph['Actual'],
                     name='Actual',
                     marker_color = 'grey',
                     opacity=0.4,
                     marker_line_color='grey',
                     marker_line_width=2,
                     text=df_people_graph['Actual'],
                     textfont=dict(color='#ffffff', family='Lato', size=20),
                     textposition='outside'),
              row = 1, col = 2)

# add first scatter trace at row = 1, col = 2
fig.add_trace(go.Scatter(x=df_people_graph['Labels'], 
                        y=df_people_graph['Target'],
                        mode='markers+text+lines' ,
                        line=dict(color='#00E487'), 
                        marker=dict(size=10), 
                        name='Target', 
                        text=df_people_graph['Target'],
                        textfont=dict(color='#ffffff', family='Lato', size=20)),
              row = 1, col = 2)

fig.add_trace(go.Table(header=dict(values=[''], line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30),
                 cells=dict(values=[df_people_table.index],align='left', line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30)),
                 row=2, col=1)
fig.add_trace(go.Table(header=dict(values=df_people_table.columns, line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30),
                 cells=dict(values=df_people_table.values, line_color='black', fill_color='black',font=dict(color='#00E487', family="Lato", size=20), height=30)),
                 row=2, col=2)

fig.update_xaxes(showgrid=False)
fig.update_yaxes(showgrid=False)
fig.update_layout(yaxis2={'visible': False, 'showticklabels': False})
fig.update_layout(plot_bgcolor="#0E1117",
                    legend=dict(yanchor="top", y=1.1, xanchor="left", x=0.5, orientation='h'),
                    margin= dict(t=0)
                    )

# calculate the maximum y value, add 10%
max_y_axis = max(actual+target) * 1.1

# update yaxis range
fig.for_each_yaxis(lambda x: x.update({'range': [0, max_y_axis]}))

# increase figure height from 600 to 900
fig.update_layout(height=900, width=1400)
fig.show()

creates:

Thanks a lot. That fixed the problem.