Hi Marc, great to see you here :-). I gave it a try and here are some partial conclusions.
First, it seems that you need to have data matched to an axis for the axis to be displayed, even when setting the range of the axis or setting visible=True
for the axis. However, you donโt need to duplicate the whole axis, you can just add a dummy transparent scatter point as I did below.
As for axes, scaleanchor
and scaleratio
allow indeed to fix the scale ratio between two axis, but not the origin, so this is not what youโre looking after here. Another solution can be to set explicitely the range of the two axes if you can live with this. A better (in my opinion) solution is to use the matches
attribute of YAxis
since this is really what you want to do: your second axis should match the first one, just with different tick labels. With this solution you have to tweak tick labels as I did below. Neither solution is perfect of course.
With an explicit range:
import pandas as pd
import plotly.graph_objs as go
obs = pd.Series({'A': 5, 'B':3})
# first trace = original values
fig = go.Figure(go.Bar(x=obs.index, y=obs, name='value', yaxis='y'))
ratio = 1. / obs.sum()
tick_pos = np.arange(0, obs.max() + 1)
tick_text = [str(ratio * pos * 100) + ' %' for pos in tick_pos]
fig.add_trace(go.Scatter(x=['A'], y=[1], yaxis='y2', marker_opacity=0, showlegend=False))
fig.update_layout(
yaxis=dict(title='Value', range=(0, 5)),
yaxis2=dict(title='Fraction of total', overlaying="y",
side='right',
tickformat='%',
range=(0, ratio*5),
gridcolor='rgba(0, 0, 0, 0)', # transparent grid lines
)
)
fig.show()
With matches
attribute
import pandas as pd
import plotly.graph_objs as go
obs = pd.Series({'A': 5, 'B':3})
# first trace = original values
fig = go.Figure(go.Bar(x=obs.index, y=obs, name='value', yaxis='y'))
ratio = 1. / obs.sum()
tick_pos = np.arange(0, obs.max() + 1)
tick_text = [str(ratio * pos * 100) + ' %' for pos in tick_pos]
fig.add_trace(go.Scatter(x=['A'], y=[1], yaxis='y2', marker_opacity=0, showlegend=False))
fig.update_layout(
yaxis=dict(title='Value'),
yaxis2=dict(title='Fraction of total', overlaying="y",
tickvals=tick_pos,
ticktext=tick_text,
side='right',
tickformat='%',
matches='y',
)
)
fig.show()