We should add these convenience methods, as the ref=x/ref=paper trick is pretty hard for people to understand.
~We'd want to be able to add these to all subplots, one subplot, or possibly a single row or a single column.~ Moved to #2140
We'd also want add_vspan and add_hspan (or vrect/hrect, not set on the names)
Related to #2140
A quick solution would be:
fig.layout.update(shapes=[{'type': 'line','y0':y_intercept,'y1': y_intercept,
'x0':str(df.x_value.min()), 'x1':str(df.x_value.max()),
'xref':'x' + str(i + 1), 'yref':'y' + str(i + 1),
'line': {'color': 'black', 'width': 1, 'dash': 'dot'}}
for i, member in enumerate(pd.unique(df.x_value))])
Though an issue arrises if you want to add both an x and y line, the second update will overwrite the former and you only see the last added line. As a workaround for that :
list(np.array([
[
# Horizontal Line
{'type': 'line',
'y0': df.y_val.min(),'y1': df_faces.y_val.max(),
'x0': df.x_val.median(), 'x1': df.x_val.median(),
'xref':'x' + str(i + 1),
'yref':'y' + str(i + 1),
'line': {'color': 'black','width': 1, 'dash': 'dot'}},
# Vertical Line
{'type': 'line',
'y0': df.y_val.median(),'y1': df..median(),
'x0':str(df.x_val.min()), 'x1':str(df.x_val.max()),
'xref':'x' + str(i+1),
'yref':'y' + str(i + 1),
'line': {'color': 'black','width': 1, 'dash': 'dot'}}
]
for i , member in enumerate(pd.unique(df.facets_val))]).ravel())
So now I see why you referred to this current usage as a bit _clunky_
Well we have fig.add_shape() already that doesn't overwrite :)
But what I'm hoping for is a way to have a single function call fig.add_hline(5) which will add a line at y=5 to all subplots, and then some options like fig.add_hline(5, row=1, col=2) for individual subplots :)
I would also ask that you consider the ability to add text to the upcoming "add_hline" and "add_vline" items.
There should also be an option to resize v/h lines to fit the plot's min and max y/x axis respectively. I notice that when I add a vline over an existing plot, it runs off the plot (as I presume is happening in the screenshots provided in this thread https://github.com/plotly/plotly_express/issues/143)
@nicholas-esterer let's start with this issue for now, without tackling the "all subplots" or "one row of subplots" just yet. Let's do the easy case to get going. cc @emmanuelle
Let's do the "hard version" with the multi-subplot targeting as part of #2140
@MrPaulAR we'll see what we can do about adding text. The underlying shapes mechanism doesn't support text today, so this may have to be done as a separate step with add_annotation although we could consider adding a text_annotation flag to these methods. Might get tricky with the various positioning arguments though.
while most discussion circles around a sugar api call, can we please have a feature to have a TRUE h/v line? timeseries &co dynamic data shifts around. especially with plotly callbacks i cant jugg the whole figure up/down the server just to extendTrace data. Please add a true horizontal / vertical line property with only one coordinate y and x respectively, since the other is infinitely extending.
Ugly workaround: oversize the x0 x1 on a hline and set the xaxis range tot he actual data so if it moves around hline shape covers due data within x0 x1 interval. BUT please do TRUE infinite x in this case. ?
This new API does indeed implement true one-coordinate infinite h/v lines that cannot be panned or zoomed away.
This has now been released as part of Plotly.py 4.12 ! https://community.plotly.com/t/announcing-plotly-py-4-12-horizontal-and-vertical-lines-and-rectangles/46783
@nicolaskruchten is it possible to use the add_vline with X-coordinates as X-axis data points?
For example, my x-axis data is class-based like [12345, 54321, 99999] and I want to plot a line only on the 54321.
I used to use this code:
fig.update_layout(
shapes=[
dict(
type="line",
xref='x', yref='y',
x0=x_data[5], x1=x_data[5],
y0=0, y1=125,
)
]
)
But apparently, this gives different results in Plotly as it does in Dash.
Plotly

Dash

(The small part on the left is the zoomed-out result, because the vertical-line was plotted at 12.000.000 (which is the class of the X_data, but Dash seems to regard is as an integer)
This only happened in the latest updates (I used to work with plotly=4.8.0 before this error)
I wanted to give the add_vlines() a try, but it only stays on the "absolute" position, and does not scroll, which is what I need.
I don't know if I should make a different Issue or not.
Hi @nathansegers, yes, please do make a separate issue for this :)
@nicolaskruchten The add_vline and add_hline methods are great, and I would really like to use them, but I have encountered a weird issue, where the line has a length of one. fig.add_hline(y=10) results in a line at 10 on the y axis but only extends from 0 to 1 on the x axis. fig.add_vline(x=1000000) results in a line at 1 million on the x axis but only extends from 0 to 1 on the y axis. Since my plot has max x values in the hundreds of billions, these lines are basically invisible (at least, until I change the axes to log scale, at which point the plot just looks strange. Screenshot of the log-scale mode below)

@jenna-jordan if you're in JupyterLab you'll need to update your lab extension to v4.12 to get this feature to work as intended, and if you're in VSCode, you'll need to wait for the VSCode extension to be updated to the latest version of the Plotly.js rendering engine, unfortunately.
@nicolaskruchten I am rendering it with streamlit, actually, so I'm not sure how that effects things.
@jenna-jordan ah, that explains it. Streamlit bundles plotly.js directly and they'll need to update their version in order to suppor this new feature.
Most helpful comment
I would also ask that you consider the ability to add text to the upcoming "add_hline" and "add_vline" items.