18

I'm trying to plot some vertical lines on a chart that has a "list" of integers (1...300) and some "values" (floats). The following works when x=[48], but when x is set to x=[48, 83, 155, 292], the following code:

pylab.plot(list, values, label='Trend', color='k', linestyle='-')
pylab.axvline(x, linewidth=1, color='g')

Generates this error:

  File "/usr/lib/pymodules/python2.7/matplotlib/pyplot.py", line 2053, in axvline
    ret = ax.axvline(x, ymin, ymax, **kwargs)   File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 3478, in axvline
    scalex = (xx<xmin) or (xx>xmax) ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

What does it mean? (I thought it was pretty funny that python pretends to knows when truth is ambiguous). Can I not pass a list to axvline?

1
  • Not related to the problem: pylab.plot(list, values... using reserved keyword list as a variable identifier actually reassigns class list when the variable is set: Try list = [1, 2, 3]; list2 = list((4,5,6)), the second assignment won't work as list is not anymore a built-in class. See #5. Commented Jan 30, 2023 at 17:31

4 Answers 4

28

No, you can't pass a list to axvline. For multiple vertical lines within one line, something like this will do

[pylab.axvline(_x, linewidth=1, color='g') for _x in x]
Sign up to request clarification or add additional context in comments.

Comments

14

For completeness, there is also the possibility of using matplotlib.pyplots vlines. This function accepts a list of x-coordinates. Furthermore, you must specify where the lines need to start/end with the arguments ymin and ymax. In the case of this question the code would be:

import matplotlib.transforms as mt

fig, ax = plt.subplots()
ax.plot(list, values, label='Trend', color='k', linestyle='-')

trans = mt.blended_transform_factory(ax.transData, ax.transAxes)
ax.vlines(x, ymin=0, ymax=1, linewidth=1, color='g', transform=trans)

Using the transform argument makes it easier to have the lines from the top to the bottom of your plot. You can read more about it here. You can also skip that argument. In that case you have to specify ymin and ymax in actual y-coordinates.

4 Comments

I like this answer vlines with transforms looks like the elegant answer here.
Even more elegant option is ax.get_xaxis_transform() which handles returning the blended transform.
"can" specify start/end is more like "very irritatingly MUST specify start/end".
Indeed, you must specify it. Changed that in the answer. That is why using transform=trans is useful, since you can just specify 0 to 1 to cover the whole y-axis
7

Instead of multiple calls to axvline we can use the plot command itself but providing the correct transformation (this is many times faster if there are many lines):

import matplotlib.transforms as tx
ax = pylab.gca()
trans = tx.blended_transform_factory(ax.transData, ax.transAxes)
pylab.plot(np.repeat(x, 3), np.tile([.25, .75, np.nan], len(x)), linewidth=2, color='g', transform=trans)

1 Comment

Is there a way to keep a sort of ID for each of the plotted lines? E.g., if x=[2,4,6], then there would be 3 lines. I would then like to be able to remove the line at 4 (i.e., index 1 of x). This is in the context of interactive plots.
1

axvline is for creating x vertical line.

Meaning at a certin x point from y-min to y-max.

x cannot be a list type.

a simple example:

axvline(x=.5, ymin=0.25, ymax=0.75)

You can read more here

If you want to create a rectangle you can use:

axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs)

in your case xmin is 1 and x man is 300.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.