4

I am new to python and matplotlib.

I am trying to highlight a few points that match a certain criteria in an already existing plot in matplotlib.

The code for the initial plot is as below:

pl.plot(t,y)
pl.title('Damped Sine Wave with %.1f Hz frequency' % f)
pl.xlabel('t (s)')
pl.ylabel('y')
pl.grid()
pl.show()

In the above plot I wanted to highlight some specific points which match the criteria abs(y)>0.5. The code coming up with the points is as below:

markers_on = [x for x in y if abs(x)>0.5]

I tried using the argument 'markevery', but it throws an error saying

'markevery' is iterable but not a valid form of numpy fancy indexing;

The code that was giving the error is as below:

pl.plot(t,y,'-gD',markevery = markers_on)
pl.title('Damped Sine Wave with %.1f Hz frequency' % f)
pl.xlabel('t (s)')
pl.ylabel('y')
pl.grid()
pl.show()

4 Answers 4

5

The markevery argument to the plotting function accepts different types of inputs. Depending on the input type, they are interpreted differently. Find a nice list of possibilities in this matplotlib example.

In the case where you have a condition for the markers to show, there are two options. Assuming t and y are numpy arrays and one has imported numpy as np,

  1. Either specify a boolean array,

    plt.plot(t,y,'-gD',markevery = np.where(y > 0.5, True, False))
    

or

  1. an array of indices.

    plt.plot(t,y,'-gD',markevery = np.arange(len(t))[y > 0.5])
    

Complete example

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(42)

t = np.linspace(0,3,14)
y = np.random.rand(len(t))

plt.plot(t,y,'-gD',markevery = np.where(y > 0.5, True, False))
# or 
#plt.plot(t,y,'-gD',markevery = np.arange(len(t))[y > 0.5])

plt.xlabel('t (s)')
plt.ylabel('y')

plt.show()

resulting in

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

markevery = np.where(y > 0.5, True, False) throws ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(). Using markevery = list(np.where(y > 0.5, True, False)) solves the issue.
Apprently markevery = np.arange(len(t))[y > 0.5] throws the exact same error. But passing the output as a list solves the problem. These errors are thrown in Matplotlib 3.1.3. Perhaps there was a breaking change somewhere along the line since 2017 when this question was first posted.
@pfabri Thanks for the notification. This indeed went wrong a long time ago. I now fixed it in github.com/matplotlib/matplotlib/pull/17276.
You're welcome. I tried editing your answer adding in the fix from my comment as an alternative, but the editing queue is full. Perhaps you could also try... If you found my comment useful... well you know, I'm starved for those rep points :)
2

markevery uses boolean values to mark every point where a boolean is True

so instead of markers_on = [x for x in y if abs(x)>0.5]

you'd do markers_on = [abs(x)>0.5 for x in y] which will return a list of boolean values the same size of y, and every point where |x| > 0.5 you'd get True

Then you'd use your code as is:

pl.plot(t,y,'-gD',markevery = markers_on)
pl.title('Damped Sine Wave with %.1f Hz frequency' % f)
pl.xlabel('t (s)')
pl.ylabel('y')
pl.grid()
pl.show()

I know this question is old, but I found this solution while trying to do the top answer as I'm not familiar with numpy and it seemed to overcomplicate things

Comments

0

The markevery argument only takes indices of type None, integer or boolean arrays as input. Since I was passing the values directly it was throwing the error.

I know it is not very pythonic but I used the below code to come up with the indices.

marker_indices = []
for x in range(len(y)):
    if abs(y[x]) > 0.5:
        marker_indices.append(x)

Comments

0

I was having this issue because I was trying to mark some points that were out of the bounds of the data frame.

For example:

some_df.shape
-> (276, 9)

markers = [1000, 1080, 1120]

some_df.plot(
    x='date',
    y=['speed'],
    figsize=(17, 7), title="Performance",
    legend=True,
    marker='o',
    markersize=10,
    markevery=markers,
)

-> ValueError: markevery=[1000, 1080, 1120] is iterable but not a valid numpy fancy index

Just make sure that the values you are giving as markers are within the bounds of the data frame you want to plot.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.