Search code examples
pythonplotlysubplot

Set column_titles and row_titles and the bottom and and the left of the plot using subplots in plotly


I’m using from plotly.subplots import make_subplots and I have two list for my column_ and row_titles:

col_name = list(df.columns)
row_name = col_name[::-1] # the inverse of col_name
fig = make_suplots(rows=5, cols=5,  start_cell="bottom-left", column_titles=col_name , row_titles=row_name )

I managed making somthing like that: (see picture)

enter image description here

As you can see the column_titles is on the top and the row_titles on the right side of the plot

It is possible to set the column_titles on the bottom and the row_titles on the left side?


Solution

  • Short answer

    fig.for_each_annotation(lambda a:  a.update(y = -0.2) if a.text in column_titles else a.update(x = -0.07) if a.text in row_titles else())
    

    Plot

    enter image description here


    The details

    Column and row labels are stored as annotations in fig.layout.annotations:

    'layout': {'annotations': [{'font': {'size': 16},
                                    'showarrow': False,
                                    'text': 'A',
                                    'x': 0.22,
                                    'xanchor': 'center',
                                    'xref': 'paper',
                                    'y': 1.0,
                                    'yanchor': 'bottom',
                                    'yref': 'paper'},
    

    Messing with annotations can quickly lead to problems since your procedures can manipulate elements that are not column or row labels. But in this case it's fairly easy to identify enough annotation attributes to ascertain that they are in fact the labels you're trying to edit. If, for example, annotation[0].text can be found in column_titles, ten you kan keep 'x': 0.22, and change 'y': 1.0 to, for example, 'y': -0.2. And that's exactly what the proposed approach does in the complete snippet below:

    Complete code

    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    
    column_titles = ['A', 'B']
    row_titles = ['1', '2']
    
    fig = make_subplots(rows=2, cols=2, start_cell="bottom-left", 
                       column_titles = column_titles,
                       row_titles = row_titles)
    
    fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
                  row=1, col=1)
    
    fig.add_trace(go.Scatter(x=[20, 30, 40], y=[50, 60, 70]),
                  row=1, col=2)
    
    fig.add_trace(go.Scatter(x=[300, 400, 500], y=[600, 700, 800]),
                  row=2, col=1)
    
    fig.add_trace(go.Scatter(x=[4000, 5000, 6000], y=[7000, 8000, 9000]),
                  row=2, col=2)
    
    fig.for_each_annotation(lambda a:  a.update(y = -0.2) if a.text in column_titles else a.update(x = -0.07) if a.text in row_titles else())
    
    fig.show()