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()
Trenton McKinney
63.1k41 gold badges169 silver badges210 bronze badges
asked Mar 18, 2017 at 8:39

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

answered Mar 19, 2017 at 0:30
4
  • 2
    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. Commented Apr 29, 2020 at 18:19
  • 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. Commented Apr 29, 2020 at 18:32
  • @pfabri Thanks for the notification. This indeed went wrong a long time ago. I now fixed it in github.com/matplotlib/matplotlib/pull/17276. Commented Apr 30, 2020 at 14:33
  • 1
    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 :) Commented Apr 30, 2020 at 15:33
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

answered Jun 21, 2019 at 12:06
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)
answered Mar 18, 2017 at 8:39
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.

answered Oct 12, 2021 at 0:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.