Soerendip
Soerendip

Reputation: 9148

How to create a bar plot with shared x-axis using plotly.express with sub-titles on top?

I wonder how to correctly create a bar plot with shared x-axis in plotly? I created this bar plot and specified fig.update_xaxes(matches='x') which to my understanding is supposed to match the axes, but apparently this is not working. Does this look like a bug or am I doing something wrong? As you can see, it looks good except for one sub-figure, which is totally off. Sometimes, using facet_row instead of facet_col gives better results, but then the titles appear at the side of the plot. The titles are sometimes quite long and would not fit there. Therefore, I am using facet_col.

fig = px.bar(data_frame=df, x='RawFile', y=plot_column, 
             facet_col='Majority protein IDs', facet_col_wrap=1, color=color, 
             color_discrete_sequence=px.colors.qualitative.Dark24,
             color_continuous_scale=px.colors.sequential.Rainbow)

n_rows = len(df['Majority protein IDs'].drop_duplicates())

height = 300*(1+n_rows)

fig.update_layout(
        height=height,        
        margin=dict( l=50, r=10, b=200, t=50, pad=0 ),
        hovermode='closest')

fig.for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
fig.update(layout_showlegend=True)
fig.update_xaxes(matches='x')

enter image description here

Strangely the y-axes are shared, but the x-axes are not. That is quite the opposite of what I am looking for.

enter image description here

# django-plotly-dash        1.6.3
# plotly                    4.14.3

I guess one solution to this would be to use facet_row however, then then I would need to move the titles from the righthand side to the top.

Upvotes: 0

Views: 467

Answers (1)

vestland
vestland

Reputation: 61084

My understanding is that you'd like all plot title to appear right on top of all subplots. There does not seem to be any built-in functionality to do this for plotly express. You always have the possility to adjust the elements of the figure, but it's a bit tricky in this case since you would have to adjust the heights of all subplots to make room for the titles. Here's my best attempt so far with a sample dataset:

enter image description here

If this is something you can use, we can take a closer look at the details.

Complete code:

import plotly.express as px
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", color="smoker", facet_row="sex")
f = fig.full_figure_for_development(warn=False)

yrefs = []
for i, elem in enumerate(fig.layout):
    if elem[:5] == 'yaxis':
        yrefs.append(fig.layout[elem].domain[1])

for i, title in enumerate(fig.layout.annotations):
    title.textangle = 0
    title.y = yrefs[i] - 0.03
#     title.x = 0.5 - ((len(title.text)+1) / 100)
    title.x = 0.40
    title.align = 'center'
    title.bgcolor='rgba(0,0,0,0.25)'
    
fig.show()

Upvotes: 1

Related Questions