Search code examples
pythonpandasplotly

Plotly: Update all yaxes fonts and give individual scale using preset layout


I have a dataset df = ['Group', 'subgroup', 'x', 'y'], for which I would like to

  • plot scatter x vs y- (Done)
  • color = subgroup (Done)
  • facet_rows = Group (Done)

Now I would like to update the plot with my own layout (my_layout); however I am runing into 2 problems:

  1. When i pass fig.update_layout(my_layout), it is only updating one yaxis, instead of all.
  2. using "matches": None, for yaxis, isn't resulting in 2 separate scales for the yaxis.

Using fig.update_yaxes(matches=None)2, updates the yaxis correctly, however I would like to have it all in my_layout, so that each time i generate a new plot I can update all the layout with one comand.

Here is the code:

#my layoyt, shoudl update all plots yaxis, and set indivuual scales for yaxis
my_layout = go.Layout({
                       "yaxis": {"matches": None, "titlefont": dict(family = 'Times new Roman',size = 30, color = 'black'), "tickfont": dict(family = 'Times new Roman',size = 30, color = 'black'),},
                       "xaxis": {"titlefont": dict(family = 'Times new Roman',size = 30, color = 'black'), "tickfont": dict(family = 'Times new Roman',size = 30, color = 'black'),},
                                     
                       })


 #the df
df =pd.DataFrame({
    "Group" : [1,1,1,1,2,2,2,2],
    "subgroup": ["A","B","C","D","E","F","G","H"],
    "x" : [1,2,3,4,1,2,3,4],
    "y" : [2,4,6,8,20,40,60,80]
    
    
})

fig = px.scatter(df, x = "x", y= "y", color="subgroup", facet_row="Group",   template = "simple_white")
fig.update_layout(my_layout)
 #with this line commented in plots yaxis update correctly, hower I am hoping to put all layout components into one object i can call.   
# fig.update_yaxes(matches=None)
fig.show()

enter image description here


Solution

  • The subplot settings in plotly are assigned in order: xaxis,xaxis2,xaxis3, and so on. y-axis is the same. Therefore, you need to add yaxis2 to your own layout. fig.layout allows you to visualize the structure of the graph in a dictionary format.

    import plotly.graph_objects as go
    import plotly.express as px
    import pandas as pd
    
     #the df
    df =pd.DataFrame({
        "Group" : [1,1,1,1,2,2,2,2],
        "subgroup": ["A","B","C","D","E","F","G","H"],
        "x" : [1,2,3,4,1,2,3,4],
        "y" : [2,4,6,8,20,40,60,80]
    })
    
    fig = px.scatter(df, x="x", y="y", color="subgroup", facet_row="Group", template="simple_white")
    
    #my layoyt, shoudl update all plots yaxis, and set indivuual scales for yaxis
    my_layout = go.Layout({"yaxis": {"matches": None,
                                     "titlefont": dict(family='Times new Roman',size=30, color='black'),
                                     "tickfont": dict(family='Times new Roman',size=30, color='black'),},
                           "yaxis2": {"matches": None,
                                     "titlefont": dict(family='Times new Roman',size=30, color='black'),
                                     "tickfont": dict(family='Times new Roman',size=30, color='black'),},
                           "xaxis": {"titlefont": dict(family='Times new Roman',size=30, color='black'),
                                     "tickfont": dict(family='Times new Roman',size=30, color='black'),},
                          })
    
    fig.update_layout(my_layout)
    fig.show()
    

    enter image description here

    Edit: To optimize the y-axis range, I can't do it in express, so the only way is to subplot it in graph_objects. I'm reusing the data created in express and subplotting it. We decided that two different ways to handle this would be more beneficial to plotly users.

    fig = make_subplots(rows=2, cols=1, shared_xaxes=True)
    fig_data = px.scatter(df, x="x", y="y", color="subgroup", facet_row="Group", template="simple_white")
    
    for i in range(8):
        if i <=3:
            fig.add_trace(fig_data.data[i])
        else:
            fig.add_trace(fig_data.data[i])
            
    #my layoyt, shoudl update all plots yaxis, and set indivuual scales for yaxis
    my_layout = go.Layout({"yaxis": {"matches": None,
                                     "titlefont": dict(family='Times new Roman',size=30, color='black'),
                                     "tickfont": dict(family='Times new Roman',size=30, color='black'),},
                           "yaxis2": {"matches": None,
                                     "titlefont": dict(family='Times new Roman',size=30, color='black'),
                                     "tickfont": dict(family='Times new Roman',size=30, color='black'),},
                           "xaxis2": {"titlefont": dict(family='Times new Roman',size=30, color='black'),
                                     "tickfont": dict(family='Times new Roman',size=30, color='black'),},
                           "template":'simple_white',
                          })
    
    fig.update_layout( my_layout)
    fig.layout.legend.tracegroupgap = 1
    fig.show()
    

    enter image description here