Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 592
MichaG Avatar asked Sep 30 '19 11:09

MichaG


People also ask

How do you add labels in Plotly?

As a general rule, there are two ways to add text labels to figures: Certain trace types, notably in the scatter family (e.g. scatter , scatter3d , scattergeo etc), support a text attribute, and can be displayed with or without markers. Standalone text annotations can be added to figures using fig.

How do you limit y axis in Plotly?

Scatter() function to make a scatter plot. The go. Figure() function takes in data as input where we set the mode as 'lines' using mode='lines'. We have used the magic underscore notation i.e layout_yaxis_range=[-8,8] to set the y-axis range from -8 to 8.

What's the difference between Plotly and Plotly Express?

The plotly. express module (usually imported as px ) contains functions that can create entire figures at once, and is referred to as Plotly Express or PX. Plotly Express is a built-in part of the plotly library, and is the recommended starting point for creating most common figures.

What does Add_trace do in Plotly?

Adding Traces New traces can be added to a plot_ly figure using the add_trace() method. This method accepts a plot_ly figure trace and adds it to the figure. This allows you to start with an empty figure, and add traces to it sequentially.


2 Answers

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

like image 83
vestland Avatar answered Sep 22 '22 16:09

vestland


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

like image 23
MichaG Avatar answered Sep 22 '22 16:09

MichaG