7

Setup:

  • I'm tring to plot a subplots with plotly library, but can't figure out how to reference a specific subplots' axis to change its' name (or other properties).
  • In Code 1 I show a simple example where I add two plots one on thop of the other with plotly.subplots.make_subplots.

Code 1

import numpy as np
from plotly.subplots import make_subplots
from math import exp

fig = make_subplots(2, 1)

x = np.linspace(0, 10, 1000)
y = np.array(list(map(lambda x: 1 / (1 + exp(-0.1 * x + 5)), x)))
fig.add_trace(
    go.Scatter(
        x=x,
        y=y,
        name=f'\N{Greek Small Letter Sigma}(x)',
        showlegend=True
    ),
    row=1,
    col=1
)

x = np.where(np.random.randint(0, 2, 100)==1)[0]
fig.add_trace(
    go.Scatter(
        x=x,
        y=np.zeros_like(x),
        name=f'Plot 2',
        mode='markers', 
        marker=dict(
                symbol='circle-open',
                color='green',
                size=5
            ),
        showlegend=True
    ),
    row=2,
    col=1
)
fig.show()

What I've Tried

I've tried using the fig.update_xaxes() after each trace addition, but it messes the plots and does not produce the desired output, as shown in Code 2.

Code 2:

import numpy as np
from plotly.subplots import make_subplots
from math import exp

fig = make_subplots(2, 1)

x = np.linspace(0, 10, 1000)
y = np.array(list(map(lambda x: 1 / (1 + exp(-0.1 * x + 5)), x)))
fig.add_trace(
    go.Scatter(
        x=x,
        y=y,
        name=f'\N{Greek Small Letter Sigma}(x)',
        showlegend=True
    ),
    row=1,
    col=1
)
fig.update_xaxes(title_text='x')
x = np.where(np.random.randint(0, 2, 100)==1)[0]
fig.add_trace(
    go.Scatter(
        x=x,
        y=np.zeros_like(x),
        name=f'Plot 2',
        mode='markers', 
        marker=dict(
                symbol='circle-open',
                color='green',
                size=5
            ),
        showlegend=True
    ),
    row=2,
    col=1
)
fig.update_xaxes(title_text='active users')
fig.show()

which results in (note the active users being printed on the top):

enter image description here

My Questions:

  1. How can I assign the top plot x axis the label x, and active users label to the x axis of the bottom plot?
  2. And in general - how can I access the properties of an individual subplot?

2 Answers 2

15

With the help from this answer I as able to solve it, by referencing the xaxis for plot on the position row=1, col=1 and the xaxis1 for the plot on the row=2, col=1 position. The full solution is in Code 1.

Code 1:

import numpy as np
from plotly.subplots import make_subplots
from math import exp

fig = make_subplots(2, 1)

x = np.linspace(0, 10, 1000)
y = np.array(list(map(lambda x: 1 / (1 + exp(-0.1 * x + 5)), x)))
fig.add_trace(
    go.Scatter(
        x=x,
        y=y,
        name=f'\N{Greek Small Letter Sigma}(x)',
        showlegend=True
    ),
    row=1,
    col=1
)
fig['layout']['xaxis'].update(title_text='x')

x = np.where(np.random.randint(0, 2, 100)==1)[0]
fig.add_trace(
    go.Scatter(
        x=x,
        y=np.zeros_like(x),
        name=f'Plot 2',
        mode='markers', 
        marker=dict(
                symbol='circle-open',
                color='green',
                size=5
            ),
        showlegend=True
    ),
    row=2,
    col=1
)
fig['layout']['xaxis2'].update(title_text='active users')

fig.show()

Cheers.

Sign up to request clarification or add additional context in comments.

2 Comments

fig.layout is slightly safer than fig['layout'].
instead of 2 fig['layout']['xaxis#'].update(title_text='asdf'), this may look better fig.update_layout(xaxis=dict(title_text='x'), xaxis2=dict(title_text='active users'))
1

You can also use .select_xaxes() to address an axis by its col and row in the grid if you are not sure what its xaxis# ID is.

This may help you if you traverse the grid in a non-sequential way or have multiple axes or different types (e.g. you mix pie and scatter types) on some subplots.

I have rendered all the necessary traces individually and then populate an empty facet 5×5 grid like this:

fig = make_subplots(rows=5, cols=5)
for i, subplot in enumerate(rendered_subplots):
    fig.add_trace(subplot.data[0], row = 1 + i//5, col = 1 + i%5)
    next(fig.select_xaxes(row=1 + i//5, col= 1 + i%5)).update(title="Speed",
                                               tickmode = 'array',
                                               tickvals = [1,2,3,4],
                                               ticktext = ['Very slow', 'Slow', 'Fast', 'Very fast'])

If you have pre-formatted the axes in each subplot that you pluck from rendered_subplots, you can take it further and graft the axes properties this way:

    rendered_xaxis = next(subplot.select_xaxes())
    this_xaxis = next(fig.select_xaxes(row = 1 + i//5, col = 1 + i%5))
    this_xaxis.update({x:rendered_xaxis[x] for x in
                       ["tickmode", "ticktext", "tickvals", "title"]})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.