Reputation: 670
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()
Upvotes: 4
Views: 13406
Reputation: 3492
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.
Upvotes: 0
Reputation: 309
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
Upvotes: 2
Reputation: 339120
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 import
ed numpy as np
,
Either specify a boolean array,
plt.plot(t,y,'-gD',markevery = np.where(y > 0.5, True, False))
or
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
Upvotes: 5
Reputation: 670
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)
Upvotes: 0