The markevery option for plot, semilogx, semilogy, and loglog plotting methods has a weird difference of behavior between plot / semilogy and semilogx / loglog, when using markevery = (float, float).
Code for reproduction
importnumpyasnpimportmatplotlib.pyplotasplt# Generate some dataX=np.linspace(-10, 10, 1000)
Y=np.sin(X)**2# Specify markersmarkers= ['o', 'v', '^', '<', '>']
defmarkevery(i):
# I tried a *lot* of values here, none were working for the 4 plotsreturn (i/50., 0.1)
plt.figure()
# First plot in normal plotplt.subplot(221)
foriinrange(10):
plt.plot(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
plt.legend()
plt.title("plt.plot(): markers are here!")
# Then plot in semilogxplt.subplot(222)
foriinrange(10):
plt.semilogx(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
plt.legend()
plt.title("plt.semilogx(): markers are NOT here!")
# And then semilogyplt.subplot(223)
foriinrange(10):
plt.semilogy(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
plt.legend()
plt.title("plt.semilogy(): markers are here!")
# Finally plot in loglogplt.subplot(224)
foriinrange(10):
plt.loglog(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
plt.legend()
plt.title("plt.loglog(): markers are NOT here!")
plt.suptitle("Weird behavior of markevery between plt.plot, plt.semilogx, plt.semilogy, plt.loglog")
plt.show()
Actual outcome
Expected outcome
One would expect the markers to be located in a similar fashion for each of the four plots method, plot, semilogx, semilogy, and loglog. The two plots on the left have markers correctly located (well spacen, with a different starting point for the different curves), and the two plots on the right do not show markers.
Note that I tried a lot of different values for the markevery parameters (here markevery = (i / 50., 0.1) for the various curves, with changing i to change the starting point of the markers), and always encounter this inconsistency between left and right.
Matplotlib version
Matplotlib version 2.0.0 (2.0.0+3337.gc15694b), with Python 3.5, on Ubuntu 16.10
Python installed with apt, latest version of Matplotlib installed with pip --upgrade.
By the way, the reason I am asking is because I use a similar trick of markevery = (i / 50., 0.1) in some research code showing half a dozen of plots in the same figure, and I am puzzled that it exhibits a different behavior between plot and semilogy: markers are perfectly displayed but not for semilogy plots...
Thanks for your quicky reply.
Well, it fixes the issue.
The corrected script can be:
importnumpyasnpimportmatplotlib.pyplotasplt# Generate some dataX=np.linspace(-10, 10, 1000)
Y=np.sin(X)**2# Specify markersmarkers= ['o', 'v', '^', '<', '>']
defmarkevery(i):
return (i/50., 0.1)
fig=plt.figure()
# First plot in normal plotax=fig.add_subplot(2, 2, 1)
foriinrange(10):
plt.plot(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
plt.legend()
plt.title("plt.plot(): markers are here!")
# Then plot in semilogxax=fig.add_subplot(2, 2, 2)
foriinrange(10):
plt.plot(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
ax.set_xscale('log') # Instead of using plt.semilogxplt.legend()
plt.title("plt.plot() with ax.set_xscale('log'): markers are NOW here! Fixed!")
# And then semilogyax=fig.add_subplot(2, 2, 3)
foriinrange(10):
plt.plot(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
ax.set_yscale('log') # Instead of using plt.semilogyplt.legend()
plt.title("plt.plot() with ax.set_yscale('log'): markers are here!")
# Finally plot in loglogax=fig.add_subplot(2, 2, 4)
foriinrange(10):
plt.plot(X, Y+i/10., marker=markers[i%len(markers)], markevery=markevery(i), label=str(i))
ax.set_xscale('log') # Instead of using plt.loglogax.set_yscale('log') # Instead of using plt.loglogplt.legend()
plt.title("plt.plot() with ax.set_xscale('log') and ax.set_yscale('log'): markers are NOW here! Fixed!")
plt.suptitle("Weird behavior of markevery between plt.plot, plt.semilogx, plt.semilogy, plt.loglog\nhttps://github.com/matplotlib/matplotlib/issues/8356")
plt.show()
And it gives what the first one should have given:
If you feel like you need help, I will try to fix the issue myself on matplotlib's code, if someone points me to the exact and correct function/part that needs to be modified. Don't hesitate to ask me, I will try my best!
Seems to me that, for safety, the self.set_xscale('log', **d) could also be done after the l = self.plot(*args, **kwargs) ?
Doing this (hacky) change, for semilogx,semilogy & loglog, will fix the issues.
In fact, I am not sure that the proper way to use set_x/yscale is before the call to plot.
Could someone confirm?
If the semantic is not properly defined, the safer way to fix bug (but not the cleanest) is to call set_xscale before and after the call to plot(...)...
OK. Clearly, I don't enough about internals of matplotlib to really understand what you explained, but I'm glad to see you seem to know what's going on.
Thanks, and good luck!
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
Naereen commented on Mar 21, 2017
Can't figure this bug, see matplotlib/matplotlib#8356
phobson commented on Mar 21, 2017
Thanks for the detailed report. What happens if you use plot and set the x/yscales afterwards?
Naereen commented on Mar 21, 2017
Thanks for your quicky reply.
Well, it fixes the issue.
The corrected script can be:
And it gives what the first one should have given:

phobson commented on Mar 21, 2017
OK. Thanks, that'll help us track it down.
Naereen commented on Mar 21, 2017
Is there a way to use set_xscale or set_yscale without having to store and use the figure and then the axis object?
phobson commented on Mar 21, 2017
Yes, but I always recommend that you explicitly create and store your Figure and Axes object.
You can do e.g., plt.xscale('log'), but then you have keep track in your head which Axes you're operating on. Kind of a mental burden, IMHO.
phobson commented on Mar 21, 2017
For instance, I would change your code to be
fig, axes = pyplot.subplots(nrows=2, ncols=2) axes[0, 0].plot(...) axes[0, 0].set_xscale('log') ax.title(...) ax.legend(...) # yada yadaalternatively, you could do:
fig, ((ax1, ax2), (ax3, ax4))= pyplot.subplots(nrows=2, ncols=2) ax1.plot(...) ax1.set_xscale('log') # yada yadaNaereen commented on Mar 21, 2017
Naereen commented on Mar 22, 2017
If you feel like you need help, I will try to fix the issue myself on matplotlib's code, if someone points me to the exact and correct function/part that needs to be modified. Don't hesitate to ask me, I will try my best!
phobson commented on Mar 22, 2017
Start digging at e.g., https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py#L1551
Naereen commented on Mar 22, 2017
Seems to me that, for safety, the self.set_xscale('log', **d) could also be done after the l = self.plot(*args, **kwargs) ?
Doing this (hacky) change, for semilogx,semilogy & loglog, will fix the issues.
Naereen commented on Mar 22, 2017
In fact, I am not sure that the proper way to use set_x/yscale is before the call to plot.
Could someone confirm?
If the semantic is not properly defined, the safer way to fix bug (but not the cleanest) is to call set_xscale before and after the call to plot(...)...
6 remaining items
Naereen commented on Mar 23, 2017
OK. Clearly, I don't enough about internals of matplotlib to really understand what you explained, but I'm glad to see you seem to know what's going on.
Thanks, and good luck!
Naereen commented on May 11, 2017
Will this be included for the 2.1 release?
phobson commented on May 11, 2017
@Naereen we've milestoned it to be fixed by 2.1, but that's not a 100% guarantee.
Naereen commented on Jun 19, 2017
Hi,
Any update? Any help needed?
tacaswell commented on Jun 19, 2017
Any help working on this would be appreciated :)
Does setting markevery on a line object correctly recompute the locations with the current scale?
Naereen commented on Jun 22, 2017
Yes
github-actions commented on Apr 10, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
ksunden commented on Apr 10, 2023
This seems to have been fixed somewhere along the way, not too sure where:
QuLogic commented on Apr 11, 2023
This was fixed by #9477 (because the markevery calculation produces all nan and thus plots nowhere.)