Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

Drawing vertical line on histogram in subplot but yref='paper' is not working

I am trying to plot a vertical line on a specific x-mark within a histogram in a subplot. In order to have it go from the x-axis to an appropriate height of 90% of plotting height I used yref=‘paper’ but it does not seem to make a difference and the line goes up to the absolute value 0.9 (see right subplot). Is this a bug or am I using it the wrong way? Is there any way of finding the y-axis range of the histogram so that I can set the height of the line manually (like in the left subplot where I guessed it)?

Thanks!

Edit to clarify: I wanted something like in the left subplot but without having to guess the height of the vertical line.

from plotly.subplots import make_subplots
import plotly.graph_objects as go
from plotly.offline import plot
import numpy as np

rng = np.random.RandomState(10)
a = rng.normal(size=1000)


fig = make_subplots(rows=1, cols=2)

fig.add_trace(
    go.Histogram(x=a, histnorm='percent'),
    row=1, col=1
)

fig.add_trace(
    go.Histogram(x=a, histnorm='percent'),
    row=1, col=2
)


fig.add_shape(
        go.layout.Shape(type='line', xref='x', yref='y',
                        x0=0, y0=0, x1=0, y1=9.3, line={'dash': 'dash'}),
                        row=1, col=1
)

fig.add_shape(
        go.layout.Shape(type='line', xref='x', yref='paper',
                        x0=0, y0=0, x1=0, y1=0.9, line={'dash': 'dash'}),
                        row=1, col=2
)


plot(fig, filename='test.html')

Not much time to investigate at the moment, but it works well outside subplots

from plotly.subplots import make_subplots
import plotly.graph_objects as go
from plotly.offline import plot
import numpy as np

rng = np.random.RandomState(10)
a = rng.normal(size=1000)

fig = go.Figure()
fig.add_trace(
    go.Histogram(x=a, histnorm='percent')
)
fig.add_shape(
        go.layout.Shape(type='line', xref='x', yref='paper',
                        x0=0, y0=0, x1=0, y1=0.9, line={'dash': 'dash'}),
)
fig.show()

Thanks for the reply. This is also what I noticed but for my project I need to use a subplot. I now tried not specifying yref and y1 (see code snippet below). It draws a line but y1 seems to default to 2.75 for whatever reason… Any other ideas from the community on how to draw this line?

fig.add_shape(
        go.layout.Shape(type='line', xref='x',
                        x0=0, y0=0, x1=0, line={'dash': 'dash'}),
                        row=1, col=2
)

It seems that when you specify yref='paper' in a subplots in add_shape this is ignored (I saw this by doing print(fig) on the fig object). You can force the behaviour by doing

from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np

rng = np.random.RandomState(10)
a = rng.normal(size=10)

fig = make_subplots(1, 2)
fig.add_trace(
    go.Histogram(x=a, histnorm='percent'), 1, 1
)
fig.add_trace(
    go.Histogram(x=a, histnorm='percent'), 1, 2
)
fig.add_shape(
        go.layout.Shape(type='line', xref='x', yref='paper',
                        x0=0., y0=0, x1=0., y1=0.9, line={'dash': 'dash'}), row=1, col=1
)
fig.layout.shapes[0]['yref']='paper'
fig.show()
3 Likes

Probably it’s because it’s not very safe to use paper in subplots when you have multiple rows and columns… but it seems that you can override this behaviour.

Thanks Emanuelle for this idea and the explanation! In my actual plot I indeed use 2 rows and several columns of subplots and it is not very easy to get the line into the right position. The ‘paper’ reference seems to span from the lower end of the bottom plot to the upper end of the top plot now. With a few iterations I have managed to put the line now where I wanted it.

This workaround might not be very elegant but it works reproducibly enough so that I can get what I wanted without redoing all the work I have put in so far.

Thanks again! This saves me a lot of time now! :smiley:

Yes, we don’t have the equivalent of paper per subplot…

I am unable to use ‘paper’ in a non-subplot chart.

Using ‘y’, the lines appear on the chart. With ‘paper’ they do not.

Update:
I was specifying the y0 as the min val and y1 as the max val. If I do not specify these, the lines appear, but they appear in the middle of the y-axis and extend out from the middle approx 1/4 of the distance to either axis.

I specified y0 = 0 and y1 = 1 and the lines now extend the length of the y-axis.

Thanks Emmanuelle for the solution above. I worry that this behavior can disappear any time! I think it is useful from the users’ perspective to specify the ‘paper’ reference in subplots. The reference then being the subplot, and not the entire figure.

Now I do this right after adding the shape:

fig.layout.shapes[-1]['xref']='paper'

Thank you @javierggt; your method works, but I found the solution by looking at fig.layout.shapes.

when fig.add_vline() is used, the line is drawn correctly. So I found that the solution is using yref="y2 domain"

fig.add_shape(
        go.layout.Shape(type='line', xref='x', yref='y2 domain',
                        x0=0, y0=0, x1=0, y1=0.9, line={'dash': 'dash'}),
)

Moreover, it’s not required to call go.layout.Shape. you can use add_shape directly.

fig.add_shape(
        type="line", xref='x', yref='y2 domain',
                        x0=0, y0=0, x1=0, y1=0.9, line_dash="dash"
    )