MichaG
MichaG

Reputation: 477

Single axis caption in plotly express facet plot

I am learning to use pyplot.express and struggle with the following design problem: In faceted plots, the axis title is repeated for every subplot (in the example case 'petal width (cm)'). Is there a way to get a single axis label for all subplots on faceted plots using pyplot.express?

thanks, Michael

Minimal example:

from sklearn.datasets import load_iris
import plotly.express as px
import pandas as pd
import numpy as np

# import iris-data
iris = load_iris()
df= pd.DataFrame(data= np.c_[iris['data'], iris['target']], columns= iris['feature_names'] + ['target'])
df['species'] = pd.Categorical.from_codes(iris.target, iris.target_names)

# plot using pyplot.express
fig = px.bar(df, x="sepal length (cm)", y="petal width (cm)", color = 'petal length (cm)', facet_row="species")
fig.show()

Iris facet plot

Upvotes: 14

Views: 10789

Answers (3)

Zach Langer
Zach Langer

Reputation: 161

Here's the Plotly native way to do this

    fig.update_yaxes(title='')
    fig.update_layout(yaxis2=dict(title="Custom Title"))

Upvotes: 4

vestland
vestland

Reputation: 61084

For this particular case, after your example snippet, just run

fig['layout']['yaxis']['title']['text']=''
fig['layout']['yaxis3']['title']['text']=''
fig.show()

Or, for a more general approach for multiple subplots, just run:

fig.for_each_yaxis(lambda y: y.update(title = ''))
# and:
fig.add_annotation(x=-0.1,y=0.5,
                   text="Custom y-axis title", textangle=-90,
                    xref="paper", yref="paper")

I've also included a title for all y-axes using fig.add_annotation() and made sure it's always placed in the center of the plot by specifying yref="paper"

Plot:

enter image description here

Upvotes: 14

MichaG
MichaG

Reputation: 477

Thanks @vestland that helped alot!

I figured out a way for a more flexible design (multiple facet_rows) based on your answer:

First I needed to remove all subplot axes:

for axis in fig.layout:
    if type(fig.layout[axis]) == go.layout.YAxis:
        fig.layout[axis].title.text = ''

The next step was the to add an Annotation instead of an axis, as the yaxis attribute in the layout always modifies the scaling of one of the axes and messes up the plot. Searching for annotations, I found a link how to add a custom axis. xref='paper' and yref='paper' are required to position the label independently of the subplots.

fig.update_layout(
    # keep the original annotations and add a list of new annotations:
    annotations = list(fig.layout.annotations) + 
    [go.layout.Annotation(
            x=-0.07,
            y=0.5,
            font=dict(
                size=14
            ),
            showarrow=False,
            text="Custom y-axis title",
            textangle=-90,
            xref="paper",
            yref="paper"
        )
    ]
)

pyplot

Upvotes: 10

Related Questions