In Matplotlib, I make dashed grid lines as follows:
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.yaxis.grid(color='gray', linestyle='dashed')
however, I can't find out how (or even if it is possible) to make the grid lines be drawn behind other graph elements, such as bars. Changing the order of adding the grid versus adding other elements makes no difference.
Is it possible to make it so that the grid lines appear behind everything else?
According to this - http://matplotlib.1069221.n5.nabble.com/axis-elements-and-zorder-td5346.html - you can use Axis.set_axisbelow(True)
(I am currently installing matplotlib for the first time, so have no idea if that's correct - I just found it by googling "matplotlib z order grid" - "z order" is typically used to describe this kind of thing (z being the axis "out of the page"))
To me, it was unclear how to apply andrew cooke's answer, so this is a complete solution based on that:
ax.set_axisbelow(True)
ax.yaxis.grid(color='gray', linestyle='dashed')
If you want to validate the setting for all figures, you may set
plt.rc('axes', axisbelow=True)
or
plt.rcParams['axes.axisbelow'] = True
It works for Matplotlib>=2.0.
I had the same problem and the following worked:
[line.set_zorder(3) for line in ax.lines]
fig.show() # to update
Increase 3to a higher value if it does not work.
You can also set the zorder kwarg in matplotlib.pyplot.grid
plt.grid(which='major', axis='y', zorder=-1.0)
You can try to use one of Seaborn's styles. For instance:
import seaborn as sns
sns.set_style("whitegrid")
Not only the gridlines will get behind but the looks are nicer.
For some (like me) it might be interesting to draw the grid behind only "some" of the other elements. For granular control of the draw order, you can use matplotlib.artist.Artist.set_zorder on the axes directly:
ax.yaxis.grid(color='gray', linestyle='dashed')
ax.set_zorder(3)
This is mentioned in the notes on matplotlib.axes.Axes.grid.
Related
I've done a fair amount of research on adding a colorbar to a plot but I'm still really confused about how to add one. The examples I've seen use different ways of doing so, which just confuses me because I don't get what the "right" way is.
I've seen there is a colorbar method and a colorbar() function, so what should one use to simply add a colorbar?
Some examples do this:
fig,ax = plt.subplots()
s = ax.scatter(x,y,cmap = coolwarm)
matplotlib.colorbar.ColorbarBase(ax=ax, cmap=coolwarm, values=sorted(v),
orientation="horizontal")
While some others simply call the function:
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
image = np.random.poisson(10., (100, 80))
i = ax.imshow(image, interpolation='nearest')
fig.colorbar(i)
I'm probably missing something here, but I just don't see how these both create a colorbar (I just copied the code for the colorbar and excluded that of the data).
My question is simply: what is the simplest way to add a colorbar to a plot?
Thanks!
The first example you quote creates an instance of ColorbarBase. This is usually not the recommended way; there might be some exceptions, but in general there is absolutely no reason to use this.
The second example you quote is one or even the way to create a colorbar inside a figure. Using this, you are on the save side. Using the colorbar method of the figure instance makes it clear in which figure to place the colorbar and supplying the respective ScalarMappable (in this case an AxesImage) ensures that the colorbar uses the correct colors from that ScalarMappable.
fig, ax = plt.subplots()
im = ax.imshow(image)
fig.colorbar(im)
or
fig, ax = plt.subplots()
sc = ax.scatter(x,y, c=something)
fig.colorbar(sc)
There is an even easier method, which would be to simply call
plt.colorbar()
Note however that this may lead to confusions as it tries to automatically determine the plot for which the colorbar should be created. Thus, there is some chance that it fails and I would not recommend using it.
I'm trying to write a simple immune system simulator. I'm modeling infected tissue as a simple grid of cells and various intracellular signals, and I'd like to animate movement of cells in one plot and the intensity of viral presence in another as the infection progresses. I'm doing so with the matshow function provided by matplotlib. However, when I plot the two next to each other, the full grid gets clipped unless I stretch out the window myself. I can't address the problem at all when saving to an mp4.
Here's the default view, which is identical to what I observe when saving to mp4:
And here's what it looks like after stretching out the viewer window
I'm running Python 2.7.9 with matplotlib 1.4.2 on OS X 10.10.2, using ffmpeg 2.5.2 (installed via Homebrew). Below is the code I'm using to generate the animation. I tried using plt.tight_layout() but it didn't affect the problem. If anyone has any advice as to how to solve this, I'd really appreciate it! I'd especially like to be able to save it without viewing with plt.show(). Thanks!
def animate(self, fname=None, frames=100):
fig, (agent_ax, signal_ax) = plt.subplots(1, 2, sharey=True)
agent_ax.set_ylim(0, self.grid.shape[0])
agent_ax.set_xlim(0, self.grid.shape[1])
signal_ax.set_ylim(0, self.grid.shape[0])
signal_ax.set_xlim(0, self.grid.shape[1])
agent_mat = agent_ax.matshow(self.display_grid(),
vmin=0, vmax=10)
signal_mat = signal_ax.matshow(self.signal_display(virus),
vmin=0, vmax=20)
fig.colorbar(signal_mat)
def anim_update(tick):
self.update()
self.diffuse()
agent_mat.set_data(self.display_grid())
signal_mat.set_data(self.signal_display(virus))
return agent_mat, signal_mat
anim = animation.FuncAnimation(fig, anim_update, frames=frames,
interval=3000, blit=False)
if fname:
anim.save(fname, fps=5, extra_args=['-vcodec', 'libx264'])
else:
plt.show()
According to the matplotlib documentation
Because of how matshow() tries to set the figure aspect ratio to be the one of the array, if you provide the number of an already existing figure, strange things may happen.
I think you're better off using imshow instead (which I believe is what matshow calls. That has an aspect keyword argument which you could use if it doesn't work automatically.
Also according to the matplotlib documentation,
Sets origin to ‘upper’, ‘interpolation’ to ‘nearest’ and ‘aspect’ to equal.
I think you want to do the first two, but leave aspect as auto.
Well, one simple solution would be to just specify the width of the figure when creating it:
fig, (agent_ax, signal_ax) = plt.subplots(1, 2, sharey=True,
figsize=(16,6))
Using Pandas to plot in I-Python Notebook, I have several plots and because Matplotlib decides the Y axis it is setting them differently and we need to compare that data using the same range.
I have tried several variants on: (I assume I'll need to apply the limits to each plot.. but since I can't get one working... From the Matplotlib doc it seems that I need to set ylim, but can't figure the syntax to do so.
df2250.plot(); plt.ylim((100000,500000)) <<<< if I insert the ; I get int not callable and if I leave it out I get invalid syntax. anyhow, neither is right...
df2260.plot()
df5.plot()
I'm guessing this was a feature added after this answer was accepted in 2013; DataFrame.plot() now exposes a ylim parameter that sets the y axis limits:
df.plot(ylim=(0,200))
See pandas documentation for details.
Pandas plot() returns the axes, you can use it to set the ylim on it.
ax1 = df2250.plot()
ax2 = df2260.plot()
ax3 = df5.plot()
ax1.set_ylim(100000,500000)
ax2.set_ylim(100000,500000)
etc...
You can also pass an axes to Pandas plot, so plotting it in the same axes can be done like:
ax1 = df2250.plot()
df2260.plot(ax=ax1)
etc...
If you want a lot of different plots, defining the axes beforehand and within one figure might be the solution that gives you the most control:
fig, axs = plt.subplots(1,3,figsize=(10,4), subplot_kw={'ylim': (100000,500000)})
df2260.plot(ax=axs[0])
df2260.plot(ax=axs[1])
etc...
Is there a way to whiten out the background of the axis label so that when it crosses the axis line itself, the latter does not run through it?
For example, this script (the best I managed so far)
#!/usr/bin/python
import matplotlib.pyplot as plt
xx=[1,2,3]
yy=[2,3,4]
dy=[0.1,0.2,0.05]
fig=plt.figure()
ax=fig.add_subplot(111)
ax.errorbar(xx,yy,dy,fmt='ro-',ms=6,elinewidth=4)
ax.set_xlim([0.,3.4])
ax.set_ylim([0.,4.4])
ax.set_xlabel(r'$T/t$',fontsize=16)
ax.set_ylabel(r'$S(\mathbf{Q})L^{1+\eta}$',fontsize=16)
# position the axis labels
ax.xaxis.set_label_coords(1,0)
ax.yaxis.set_label_coords(0.1,0.93)
ax.yaxis.get_label().set_rotation('horizontal')
ax.yaxis.get_label().set_backgroundcolor('w')
#ax.yaxis.get_label().set_zorder(222) #doesn't do the trick
plt.show()
produces almost what I'm looking for, but still the y-axis runs over the label: .
By default, the left spine has a zorder of 2.5. For some reason this seems to cause problems; maybe there's something in the code which only works if they're integral? Anyway, if you add
ax.spines['left'].set_zorder(2)
or more generally
ax.spines['left'].set_zorder(ax.yaxis.get_label().get_zorder()-1)
before the show, it should work. Also, set_ylabel returns the ylab object itself, so if you use "ylab = ax.set_ylabel(stuff)" you can avoid all the ax.yaxis.get_label() calls later.
Does this link help you?
http://matplotlib.sourceforge.net/faq/howto_faq.html#automatically-make-room-for-tick-labels
You can simply shift the y-axis to the right to allows some space for the $S(\mathbf{Q})L^{1+\eta}$ mark be fully placed before the axis line.
In Matplotlib, I make dashed grid lines as follows:
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.yaxis.grid(color='gray', linestyle='dashed')
however, I can't find out how (or even if it is possible) to make the grid lines be drawn behind other graph elements, such as bars. Changing the order of adding the grid versus adding other elements makes no difference.
Is it possible to make it so that the grid lines appear behind everything else?
According to this - http://matplotlib.1069221.n5.nabble.com/axis-elements-and-zorder-td5346.html - you can use Axis.set_axisbelow(True)
(I am currently installing matplotlib for the first time, so have no idea if that's correct - I just found it by googling "matplotlib z order grid" - "z order" is typically used to describe this kind of thing (z being the axis "out of the page"))
To me, it was unclear how to apply andrew cooke's answer, so this is a complete solution based on that:
ax.set_axisbelow(True)
ax.yaxis.grid(color='gray', linestyle='dashed')
If you want to validate the setting for all figures, you may set
plt.rc('axes', axisbelow=True)
or
plt.rcParams['axes.axisbelow'] = True
It works for Matplotlib>=2.0.
I had the same problem and the following worked:
[line.set_zorder(3) for line in ax.lines]
fig.show() # to update
Increase 3to a higher value if it does not work.
You can also set the zorder kwarg in matplotlib.pyplot.grid
plt.grid(which='major', axis='y', zorder=-1.0)
You can try to use one of Seaborn's styles. For instance:
import seaborn as sns
sns.set_style("whitegrid")
Not only the gridlines will get behind but the looks are nicer.
For some (like me) it might be interesting to draw the grid behind only "some" of the other elements. For granular control of the draw order, you can use matplotlib.artist.Artist.set_zorder on the axes directly:
ax.yaxis.grid(color='gray', linestyle='dashed')
ax.set_zorder(3)
This is mentioned in the notes on matplotlib.axes.Axes.grid.