Set sqrt as yaxis scale from dropdown or button-Python/Plotly

Viewed 571

From this example here : Set linear or log axes from button or dropdown menu I can use a button to change the yaxis from linear to log. However i need to change it to sqrt.

I have looked at from Plotly: reference layout axis I have found that there is no type ("sqrt")

type Code: fig.update_yaxes(type=) Type: enumerated , one of ( "-" | "linear" | "log" | "date" | "category" | "multicategory" ) Default: "-" Sets the axis type. By default, plotly attempts to determined the axis type by looking into the data of the traces that referenced the axis in question.

Here is the exmaple code:

import plotly.graph_objects as go

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
    y=[8, 7, 6, 5, 4, 3, 2, 1, 0]
))

fig.add_trace(go.Scatter(
    x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
    y=[0, 1, 2, 3, 4, 5, 6, 7, 8]
))

fig.update_layout(title_text="CIR plot ",
                          updatemenus=[
            dict(
                 buttons=list([
                     dict(label="Linear",  method="update", args=[{"yaxis":{"type": "linear"}}]),
                     dict(label="Log", method="update", args=[{"yaxis":{"type": "log"}}]),
                                  ]),
            )])

 #UPDATE Y AXIS HERE
fig.update_layout( updatemenus=[
            dict(
                 buttons=list([
                     dict(label="Linear-ID",  
                          method="relayout", 
                          args=[{"yaxis.type": "linear"}]),
                     dict(label="Log-ID", 
                          method="relayout", 
                          args=[{"yaxis.type": "log"}]),
                                  ]),
            )])
fig.show()

Is there a way to use a button to update the scale to sqrt ?

2 Answers

To my knowledge there's currently no way to specify sqrt as scale for the axis that would trigger a visual change to the axis labels like the case is for fig.update_xaxes(type="log"):

enter image description here

But you don't really have to in order to change the data associated with the yaxis to display the square roots of a given series. The complete snippet below produce a figure that will easily let you switch between displaying the raw data and a series with square roots.

Plot 1: Raw data

enter image description here

Plot 2: np.sqrt

enter image description here

Complete code:

import numpy as np
import plotly.graph_objects as go
import plotly.express as px
df = px.data.gapminder().query("year == 2007")

# figure setup
fig = go.Figure()
fig.add_scatter(mode="markers", x=df["gdpPercap"], y=df["lifeExp"])
fig.add_scatter(mode="markers", x=df["gdpPercap"], y=np.sqrt(df["lifeExp"]), visible = False)

# buttons for updatemenu
buttons = [dict(method='restyle',
                label='linear',
                visible=True,
                args=[{'label': 'linear',
                       'visible':[True, False],
                      }
                     ]),
           dict(method='restyle',
                label='sqrt',
                visible=True,
                args=[{'label': 'linear',
                       'visible':[False, True],
                      }
                     ])]
           
# specify updatemenu        
um = [{'buttons':buttons,
      'direction': 'down'}
      ]

fig.update_layout(updatemenus=um)
# fig.update_yaxes(type="log")
fig.show()

I think the desired output, in the case of switching axis domains, is to transform the shape of the curve but keep the original y values (for instance with log axis). Since plotly does not have square root axis option you need to transform the data (as in @vestland's approach) but also transform the axis values. This can be done with a combination of the tickvals and ticktext options for the desired axis (see here and here)

  • tickvals=ysqrt this sets the values at which ticks on this axis appear to the square root of ybase
  • ticktext=ybase this sets the text displayed at the ticks position, here keeping the ybase values

Consider this example without the transformation:

import plotly.graph_objects as go

fig = go.Figure()

ybase=np.array([0, 1, 4, 9, 16, 25, 36, 49, 64])
ysqrt=np.sqrt(ybase)

fig.add_trace(go.Scatter(x=np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]),y=ybase))

fig.show()

enter image description here

And then with:

fig.add_trace(go.Scatter(x=np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]),y=ysqrt))
fig.update_yaxes(tickvals=ysqrt, ticktext=ybase)
fig.show()

enter image description here

We now have a linear representation of this curve but keeping the original y values.

Related