Is there a way to get rid of tick labels altogether when creating an array of subplots in Matplotlib? I am currently needing to specify each plot based on the row and column of a larger data set to which the plot corresponds. I've attempted to use the ax.set_xticks([]) and the similar y-axis command, to no avail.
I recognize that it's probably an unusual request to want to make a plot with no axis data whatsoever, but that's what I need. And I need it to automatically apply to all of the subplots in the array.
You have the right method. Maybe you are not applying the set_xticks to the correct axes.
An example:
import matplotlib.pyplot as plt
import numpy as np
ncols = 5
nrows = 3
# create the plots
fig = plt.figure()
axes = [ fig.add_subplot(nrows, ncols, r * ncols + c) for r in range(0, nrows) for c in range(0, ncols) ]
# add some data
for ax in axes:
ax.plot(np.random.random(10), np.random.random(10), '.')
# remove the x and y ticks
for ax in axes:
ax.set_xticks([])
ax.set_yticks([])
This gives:
Note that each axis instance is stored in a list (axes) and then they can be easily manipulated. As usual, there are several ways of doing this, this is just an example.
Even more concise than #DrV 's answer, remixing #mwaskom's comment, a complete and total one-liner to get rid of all axes in all subplots:
# do some plotting...
plt.subplot(121),plt.imshow(image1)
plt.subplot(122),plt.imshow(image2)
# ....
# one liner to remove *all axes in all subplots*
plt.setp(plt.gcf().get_axes(), xticks=[], yticks=[]);
Note: this must be called before any calls to plt.show()
The commands are the same for subplots
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.plot([1,2])
ax1.tick_params(
axis='x', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom='off', # ticks along the bottom edge are off
top='off', # ticks along the top edge are off
labelbottom='off' # labels along the bottom edge are off)
)
plt.draw()
You can get rid of the default subplot x and y ticks with simply running the following codes:
fig, ax = plt.subplots()
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
for i in range(3):
ax = fig.add_subplot(3, 1, i+1)
...
Just by adding the 2 aforementioned lines just after fig, ax = plt.subplots() you can remove the default ticks.
One can remove the xticks or yticks by
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
If you want to turn off also the spines, so having no axis at all, you can use:
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
And if you want to turn everything off at once, use:
ax.axis("off")
Related
I have an ax.stackplot showing population of different groups over time. The x-axis is time and the y-axis is population. I am showing time at major labels 1 year and minor labels 1 month, however, changes in the data occur more frequently at "events". I'd like to show labels for these events along the x-axis, kind of how I have it sketched out in the image here:
I've attempted adding a second axis with plt.axes(), but this second axis is overwriting the ticks of my first axis for some reason. Does anyone have any suggestions for how to accomplish this?
Thank you!
If you don't have too many points, I think the best way to do this is adding text to your axes using ax.text:
from matplotlib import pyplot
import matplotlib
import numpy as np
# Random plot
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
fig, ax = pyplot.subplots()
ax.plot(t, s)
# ax.text(x, y, text, rotation)
ax.text(0, -0.35, "Event 1", rotation=90) # rotation=90 is easier to read, for me
ax.text(0.5, -0.35, "Event 2", rotation=-90) # opposite rotation
ax.text(0.75, -0.35, "Event 3", rotation=-90)
# This gives some space at the bottom of the figure
# so that the text is visible
fig.subplots_adjust(bottom=0.2)
pyplot.show()
Result:
Check the Axes.text documentation for more info.
Thank you for the responses, I was able to come up with a solution based on your suggestions. The solution involves using ax.twiny() to create a second axes object, and then specifying the second x-axis data points and labels. Below is a simple example for those interested:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
# Create some meaningless data for testing.
x = np.arange(0, 10)
y = np.full(10, len(x))
# Set up figure and set axes parameters.
fig = plt.figure(num=None, figsize=(10, 8), dpi=80, facecolor='w', edgecolor='k')
ax = plt.axes()
ax.xaxis.set_minor_locator(ticker.FixedLocator([1, 3, 5, 7, 9]))
# Get a second axes (for secondary labels) and set parameters.
axl = ax.twiny()
axl.tick_params(axis='x', bottom=True, labelbottom=True, labeltop=False, top=False, length=15, colors=[.5,.5,.5])
# Plot data on primary axes
ax.bar(x, y)
interval = ax.xaxis.get_view_interval()
# Set label properties on secondary axes (for secondary labels)
axl.xaxis.set_view_interval(*interval)
axl.xaxis.set_ticklabels(['a', 'b'])
axl_loc = ticker.FixedLocator([0.5, 4.75])
axl.xaxis.set_major_locator(axl_loc)
plt.show()
Consider the following code:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(19680801)
data = np.random.randn(2, 100)
fig, axs = plt.subplots(2, 2, figsize=(5, 5))
axs[0, 0].hist(data[0])
axs[1, 0].scatter(data[0], data[1])
axs[0, 1].plot(data[0], data[1])
axs[1, 1].hist2d(data[0], data[1])
plt.show()
I am aware that in order to create subplots you ned to write the line:
fig, axs = plt.subplots(2, 2, figsize=(5, 5)
However my question is concerning the meaning of this line, as in what does it actually achieve by producing the variables fig and axs, and why later on we use ax[0,0] as opposed to fig[0,0]
fig describes the figure as a whole, but the axs in this case refers to all the subplots within the figure. Since you defined 2 rows and 2 columns of subplots, you call each subplot with axs[0,0] for the top left and axs[1,1] for the bottom right subplot. In order to change the size of a subplot you have to change the size of the overall figure in which the subplots are embedded.
The difference is subtle, but multiple subplots or just one subplot can be found in a figure. So to plot a line you would do this on the subplot axes and not on the figure.
In matplotlib, if I increase the size of the ticklabels, the size of the subplots will keep unchanged but the whole figure will expand itself.
For example:
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(2, 1)
ax2.set_yticklabels(['a long and big label'], fontsize=26)
I want to know how to set the subplots to automatically adjust their size to accommodate the ticklabels so that the whole area a subplot takes will keep unchanged, like the following:
First one should note that the total area a subplot takes is unchanged by default. The code from the question result in
where the label is simply cut. When the code is run in jupyter notebook with the inline backend, the resulting png image is however expanded to contain everything, even parts initially outside the figure.
You can automatically adjust all the subplots to nicely fit into the figure via constrained_layout or tight_layout(). E.g.
fig, (ax1, ax2) = plt.subplots(2, 1, constrained_layout=True)
# ...
or
fig, (ax1, ax2) = plt.subplots(2, 1)
ax2.set_yticklabels(['a long and big label'], fontsize=26)
fig.tight_layout()
There is however no automatic way to only adjust one of the subplots independent of the others. For such case one would need to manually calculate the space needed.
import matplotlib.pyplot as plt
fig = plt.figure()
gs = fig.add_gridspec(2,2)
ax1 = fig.add_subplot(gs[0,:])
ax2 = fig.add_subplot(gs[1,1])
ax2.set_yticklabels(['a long and big label'], fontsize=26)
fig.canvas.draw()
bb = ax2.yaxis.get_tightbbox(fig.canvas.get_renderer())
labelwidth = fig.transFigure.inverted().transform([bb.width, 0])[0]
axwidth = ax1.get_position().width
gs.set_width_ratios([labelwidth, axwidth-labelwidth] )
ax2.set_position(gs[1,1].get_position(fig))
plt.show()
I have produced the graph shown below as intended with matplotlib and Pandas except two problems:
I can't get rid of the x axes labels (Year) for the three plots at the top (things I have tried are commented out in the code attached), and I could not centre the y axis label.
It seem trivial but I can't get it to work.
Any suggestions?
Thanks
fig, axes = plt.subplots(nrows=4, ncols=1, sharex=True, figsize=(12, 12))
for i, crop in enumerate(['Cabbage','Green beans','Potato', 'Wheat']):
mean_irr_soil[crop].plot(kind='bar', ax=axes[i], title=crop, grid=False)
axes[i].set_ylim([0, 700]) # set limit for all y axes
axes[i].tick_params(axis='x', top='off') # remove top ticks
axes[i].tick_params(axis='y', right='off') # remove right-hand ticks
axes[i].tick_params(axis='x', labelbottom='off')
if i is not 0:
axes[i].legend_.remove() # all but top graph
# if i is not 3:
# axes[i].get_xaxis().set_visible(False) # remove axis all together
# axes[i].tick_params(axis='x', labelbottom='off')
# axes[i].set_xticklabels([]) # remove x-axis labels
axes[0].legend(bbox_to_anchor=(1.1, 1.4))
axes[2].set_ylabel('Mean irrigation requirements in mm')
You need the xlabel attribute: ax.set_xlabel("").
I am plotting a multipanel figure in python using a pandas dataframe. I have used the shorter version:
df1_5.plot(subplots=True, sharex=True);
which removes xtick labels on all but the bottom figure in a 5 row by 1 column figure format.
However in order to customize the plots, I was more explicit about how I plotted and used the following code:
fig, axes = plt.subplots(nrows=5, ncols=1, figsize=(8, 5))
df11_15['V11'].plot(ax=axes[0], ylim=(0, 7)); axes[0].set_title('V1')
df11_15['V12'].plot(ax=axes[1], ylim=(0, 7)); axes[1].set_title('V12')
df11_15['V13'].plot(ax=axes[2], ylim=(-0.5, 1.0)); axes[2].set_title('V13')
df11_15['V14'].plot(ax=axes[3], ylim=(-0.5,0.5)); axes[3].set_title('V14')
df11_15['V15'].plot(ax=axes[4], ylim=(-0.5, 0.5)); axes[4].set_title('V15')
I would like to remove the xticklabels from the upper four plots. Can you tell me how to do this?
I tried:
axes[3].set_axisticklabels()
but was told there was no attribute error named this.
Try this
for label in ax[3].get_xticklabels():
label.set_visible(False)
For completeness I will also provide example on how this works in a loop
# generate 2x4 matrix of subplots
fig, axs = plt.subplots(nrows=4, ncols=2)
for i,ax in enumerate(fig.axes):
# fill histograms with random numbers
ax.hist(np.random.normal(size = 100), bins=20)
# set the same xlim so that making labels invisible makes sense
ax.set_xlim([-4,4])
# make labels invisible only if "ax" is not in the last row
if not ax.is_last_row():
for label in ax.get_xticklabels():
label.set_visible(False)