I'm trying to plot a figure without tickmarks or numbers on either of the axes (I use axes in the traditional sense, not the matplotlib nomenclature!). An issue I have come across is where matplotlib adjusts the x(y)ticklabels by subtracting a value N, then adds N at the end of the axis.
This may be vague, but the following simplified example highlights the issue, with '6.18' being the offending value of N:
import matplotlib.pyplot as plt
import random
prefix = 6.18
rx = [prefix+(0.001*random.random()) for i in arange(100)]
ry = [prefix+(0.001*random.random()) for i in arange(100)]
plt.plot(rx,ry,'ko')
frame1 = plt.gca()
for xlabel_i in frame1.axes.get_xticklabels():
xlabel_i.set_visible(False)
xlabel_i.set_fontsize(0.0)
for xlabel_i in frame1.axes.get_yticklabels():
xlabel_i.set_fontsize(0.0)
xlabel_i.set_visible(False)
for tick in frame1.axes.get_xticklines():
tick.set_visible(False)
for tick in frame1.axes.get_yticklines():
tick.set_visible(False)
plt.show()
The three things I would like to know are:
How to turn off this behaviour in the first place (although in most cases it is useful, it is not always!) I have looked through matplotlib.axis.XAxis and cannot find anything appropriate
How can I make N disappear (i.e. X.set_visible(False))
Is there a better way to do the above anyway? My final plot would be 4x4 subplots in a figure, if that is relevant.
Instead of hiding each element, you can hide the whole axis:
frame1.axes.get_xaxis().set_visible(False)
frame1.axes.get_yaxis().set_visible(False)
Or, you can set the ticks to an empty list:
frame1.axes.get_xaxis().set_ticks([])
frame1.axes.get_yaxis().set_ticks([])
In this second option, you can still use plt.xlabel() and plt.ylabel() to add labels to the axes.
If you want to hide just the axis text keeping the grid lines:
frame1 = plt.gca()
frame1.axes.xaxis.set_ticklabels([])
frame1.axes.yaxis.set_ticklabels([])
Doing set_visible(False) or set_ticks([]) will also hide the grid lines.
If you are like me and don't always retrieve the axes, ax, when plotting the figure, then a simple solution would be to do
plt.xticks([])
plt.yticks([])
I've colour coded this figure to ease the process.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
You can have full control over the figure using these commands, to complete the answer I've add also the control over the spines:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# X AXIS -BORDER
ax.spines['bottom'].set_visible(False)
# BLUE
ax.set_xticklabels([])
# RED
ax.set_xticks([])
# RED AND BLUE TOGETHER
ax.axes.get_xaxis().set_visible(False)
# Y AXIS -BORDER
ax.spines['left'].set_visible(False)
# YELLOW
ax.set_yticklabels([])
# GREEN
ax.set_yticks([])
# YELLOW AND GREEN TOGHETHER
ax.axes.get_yaxis().set_visible(False)
I was not actually able to render an image without borders or axis data based on any of the code snippets here (even the one accepted at the answer). After digging through some API documentation, I landed on this code to render my image
plt.axis('off')
plt.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False)
plt.savefig('foo.png', dpi=100, bbox_inches='tight', pad_inches=0.0)
I used the tick_params call to basically shut down any extra information that might be rendered and I have a perfect graph in my output file.
Somewhat of an old thread but, this seems to be a faster method using the latest version of matplotlib:
set the major formatter for the x-axis
ax.xaxis.set_major_formatter(plt.NullFormatter())
One trick could be setting the color of tick labels as white to hide it!
plt.xticks(color='w')
plt.yticks(color='w')
or to be more generalized (#Armin Okić), you can set it as "None".
When using the object oriented API, the Axes object has two useful methods for removing the axis text, set_xticklabels() and set_xticks().
Say you create a plot using
fig, ax = plt.subplots(1)
ax.plot(x, y)
If you simply want to remove the tick labels, you could use
ax.set_xticklabels([])
or to remove the ticks completely, you could use
ax.set_xticks([])
These methods are useful for specifying exactly where you want the ticks and how you want them labeled. Passing an empty list results in no ticks, or no labels, respectively.
You could simply set xlabel to None, straight in your axis. Below an working example using seaborn
from matplotlib import pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)
ax.set(xlabel=None)
plt.show()
Just do this in case you have subplots
fig, axs = plt.subplots(1, 2, figsize=(16, 8))
ax[0].set_yticklabels([]) # x-axis
ax[0].set_xticklabels([]) # y-axis
Related
The question
I am trying to draw grid lines from the ticks of my SecondaryAxis with
ax2.grid(color=color,linestyle='--')
nothing shows up on the figure, I believe I am in the same situation as for Format SecondaryAxis ticklabels Matplotlib, aren't I ?
However, does anybody have a workaround for the issue without reversing the scales ? I mean by reversing the scale is to have the percentages scale on the main axis and the normal scale on the secondary axis.
The full code
import matplotlib.pyplot as plt
import numpy as np
#generate dummy load duration curve
dur=2500
load = np.random.normal(60,30,dur+1)
load[::-1].sort()
x=range(0,dur+1)
perticks = np.linspace(0,1,11)
xticks = perticks*dur
# get yticks from xticks
yticks = np.interp(xticks, range(0,dur+1), load)
print(yticks)
# create figure object with axe object
fig, ax1 = plt.subplots(figsize=(16, 8))
ax1.plot(x, load)
#create second axis
ax2 = ax1.secondary_yaxis('right')
# label and color of the secondaryaxis
perlabels = ['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%']
color ='tab:blue'
ax2.set_yticks(yticks)
ax2.set_yticklabels(labels=perlabels)
ax2.tick_params(axis='y', color=color, labelcolor=color)
# draw grid lines on the secondaryaxis
ax2.grid(color=color,linestyle='--')
# do the same for x axis
ax3 = ax1.secondary_xaxis('top')
ax3.set_xticks(xticks)
ax3.set_xticklabels(labels=perlabels)
ax3.tick_params(axis='x', color=color, labelcolor=color)
ax3.grid(color=color,linestyle='--')
The output
I did some digging on this topic, and opened an issue on GitHub. Here's what I found out:
The SecondaryAxis is "quite new thing", added in matplotlib 3.1.0. (May 2019). Even the v.3.3.3 docs say that the secondary_xaxis() method is experimental.
The SecondaryAxis inherits from _AxesBase, which is an "implementation detail". It is not supposed (as of v.3.3.3) to work as Axes object, and the SecondaryAxis.grid() is not supposed to draw anything (like _AxesBase.grid() does). Although, I agree it is misleading that there is a non-working method.
Therefore, at the time of writing, .grid() is only assumed to work on primaxy axes.
Making the blue axis primary
Since .grid() only works on non-secondary axis, you make the primary axis blue, and move it to top & right.
Code
# Take the x and y-ticks for transfering them to secondary axis
xticks_orig = ax1.get_xticks()
yticks_orig = ax1.get_yticks()
# Make the primary axis blue since we want to draw grid on it
ax1.xaxis.tick_top()
ax1.yaxis.tick_right()
ax1.set_xticks(xticks)
ax1.set_yticks(yticks)
ax1.set_yticklabels(labels=perlabels)
ax1.set_xticklabels(labels=perlabels)
ax1.tick_params(axis="both", color=color, labelcolor=color)
ax1.grid(color=color, linestyle="--")
# Draw the black secondary axis
ax2 = ax1.secondary_yaxis("left")
ax3 = ax1.secondary_xaxis("bottom")
ax2.set_yticks(yticks_orig)
ax3.set_xticks(xticks_orig)
Adding grid lines manually
You could add the grid lines also manually, like this
xlim = ax1.get_xlim()
for y in ax2.get_yticks():
ax1.plot(xlim, (y, y), ls="--", color=color, lw=0.5)
ax1.set_xlim(xlim)
ylim = ax1.get_ylim()
for x in ax3.get_xticks():
ax1.plot((x, x), ylim, ls="--", color=color, lw=0.5)
ax1.set_ylim(ylim)
The output would look like this:
The difference here is now we draw lines on the figure which look like the grid lines.
To add on np8's answer, you can also use axvline to draw the lines. This has the advantage that you do not need to keep track of the y limits manually:
for x in ax2.get_xticks():
ax1.axvline(x, color=color, zorder=-1, linestyle="--", linewidth=0.5)
Note also that you will need to appropriately transform the x-coordinate to match the transform you do from ax1 to ax2.
Also, in my case I first had to render the canvas in order for the tick labels to be generated:
fig1.canvas.draw()
I'm trying to plot a figure without tickmarks or numbers on either of the axes (I use axes in the traditional sense, not the matplotlib nomenclature!). An issue I have come across is where matplotlib adjusts the x(y)ticklabels by subtracting a value N, then adds N at the end of the axis.
This may be vague, but the following simplified example highlights the issue, with '6.18' being the offending value of N:
import matplotlib.pyplot as plt
import random
prefix = 6.18
rx = [prefix+(0.001*random.random()) for i in arange(100)]
ry = [prefix+(0.001*random.random()) for i in arange(100)]
plt.plot(rx,ry,'ko')
frame1 = plt.gca()
for xlabel_i in frame1.axes.get_xticklabels():
xlabel_i.set_visible(False)
xlabel_i.set_fontsize(0.0)
for xlabel_i in frame1.axes.get_yticklabels():
xlabel_i.set_fontsize(0.0)
xlabel_i.set_visible(False)
for tick in frame1.axes.get_xticklines():
tick.set_visible(False)
for tick in frame1.axes.get_yticklines():
tick.set_visible(False)
plt.show()
The three things I would like to know are:
How to turn off this behaviour in the first place (although in most cases it is useful, it is not always!) I have looked through matplotlib.axis.XAxis and cannot find anything appropriate
How can I make N disappear (i.e. X.set_visible(False))
Is there a better way to do the above anyway? My final plot would be 4x4 subplots in a figure, if that is relevant.
Instead of hiding each element, you can hide the whole axis:
frame1.axes.get_xaxis().set_visible(False)
frame1.axes.get_yaxis().set_visible(False)
Or, you can set the ticks to an empty list:
frame1.axes.get_xaxis().set_ticks([])
frame1.axes.get_yaxis().set_ticks([])
In this second option, you can still use plt.xlabel() and plt.ylabel() to add labels to the axes.
If you want to hide just the axis text keeping the grid lines:
frame1 = plt.gca()
frame1.axes.xaxis.set_ticklabels([])
frame1.axes.yaxis.set_ticklabels([])
Doing set_visible(False) or set_ticks([]) will also hide the grid lines.
If you are like me and don't always retrieve the axes, ax, when plotting the figure, then a simple solution would be to do
plt.xticks([])
plt.yticks([])
I've colour coded this figure to ease the process.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
You can have full control over the figure using these commands, to complete the answer I've add also the control over the spines:
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# X AXIS -BORDER
ax.spines['bottom'].set_visible(False)
# BLUE
ax.set_xticklabels([])
# RED
ax.set_xticks([])
# RED AND BLUE TOGETHER
ax.axes.get_xaxis().set_visible(False)
# Y AXIS -BORDER
ax.spines['left'].set_visible(False)
# YELLOW
ax.set_yticklabels([])
# GREEN
ax.set_yticks([])
# YELLOW AND GREEN TOGHETHER
ax.axes.get_yaxis().set_visible(False)
I was not actually able to render an image without borders or axis data based on any of the code snippets here (even the one accepted at the answer). After digging through some API documentation, I landed on this code to render my image
plt.axis('off')
plt.tick_params(axis='both', left=False, top=False, right=False, bottom=False, labelleft=False, labeltop=False, labelright=False, labelbottom=False)
plt.savefig('foo.png', dpi=100, bbox_inches='tight', pad_inches=0.0)
I used the tick_params call to basically shut down any extra information that might be rendered and I have a perfect graph in my output file.
Somewhat of an old thread but, this seems to be a faster method using the latest version of matplotlib:
set the major formatter for the x-axis
ax.xaxis.set_major_formatter(plt.NullFormatter())
One trick could be setting the color of tick labels as white to hide it!
plt.xticks(color='w')
plt.yticks(color='w')
or to be more generalized (#Armin Okić), you can set it as "None".
When using the object oriented API, the Axes object has two useful methods for removing the axis text, set_xticklabels() and set_xticks().
Say you create a plot using
fig, ax = plt.subplots(1)
ax.plot(x, y)
If you simply want to remove the tick labels, you could use
ax.set_xticklabels([])
or to remove the ticks completely, you could use
ax.set_xticks([])
These methods are useful for specifying exactly where you want the ticks and how you want them labeled. Passing an empty list results in no ticks, or no labels, respectively.
You could simply set xlabel to None, straight in your axis. Below an working example using seaborn
from matplotlib import pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)
ax.set(xlabel=None)
plt.show()
Just do this in case you have subplots
fig, axs = plt.subplots(1, 2, figsize=(16, 8))
ax[0].set_yticklabels([]) # x-axis
ax[0].set_xticklabels([]) # y-axis
I created a subplot using matplotlib.pyplot. Even as I set the tick labels to empty using:
plt.xticks([ ])
plt.yticks([ ])
How can I remove these? I am new to Python and any help on the matter is appreciated.
Your figure has many subplots in it. You need to remove the ticks in each axis object of each subplot (or at least the ones you done want to appear). This can be done like this:
import matplotlib.pyplot as plt
ax1 = plt.subplot(321) # 1st subplot in 3-by-2 grid
ax1.plot(...) # draw what you want
ax1.set_xticks([], []) # note you need two lists one for the positions and one for the labels
ax1.set_yticks([], []) # same for y ticks
ax2 = plt.subplot(321) # 2nd subplot in the same grid
# do the same thing for any subplot you want the ticks removed
If you want the whole axis (borders, ticks and labels) removed you can just do this:
ax1.axis('off')
However I'd suggest typing plt.tight_layout(). It might fix your problem without requiring you to remove the ticks.
You can use the plt.tick_params option to fine tune your plots:
plt.tick_params(axis='both', which='both', right=False, left=False, top=False, bottom=False)
I'm using Seaborn to make some plots using the whitegrid style. After calling despine(), I'm seeing that the gridlines that would overlap with the axes spines have smaller linewidth than the other gridlines. But it seems like this only happens when I save the plots as pdf. I'm sharing
three different figures with different despine configurations that show the effect.
Does anyone know why this occurs? And is there a simple fix?
PDF plot with all spines
PDF plot that despines all axes
PDF plot that despines left, top, and right axes
Code:
splot = sns.boxplot(data=df, palette=color, whis=np.inf, width=0.5, linewidth = 0.5)
splot.set_ylabel('Normalized WS')
plt.xticks(rotation=90)
plt.tight_layout()
sns.despine(left=True, bottom=True)
plt.savefig('test.pdf', bbox_inches='tight')
Essentially what's happening here is that the grid lines are centered on the tick position, so the outer half of the extreme grid lines are not drawn because they extend past the limits of the axes.
One approach is to disable clipping for the grid lines:
import numpy as np
import seaborn as sns
sns.set(style="whitegrid", rc={"grid.linewidth": 5})
x = np.random.randn(100, 6)
ax = sns.boxplot(data=x)
ax.yaxis.grid(True, clip_on=False)
sns.despine(left=True)
My hacking solution now is to not despine the top and bottom axes and make them the same width as the gridlines. This is not ideal. If someone can point out a way to fix the root cause, I will really appreciate that.
I'm trying to use Python and Matplotlib to plot a number of different data sets. I'm using twinx to have one data set plotted on the primary axis and another on the secondary axis. I would like to have two separate legends for these data sets.
In my current solution, the data from the secondary axis is being plotted over the top of the legend for the primary axis, while data from the primary axis is not being plotted over the secondary axis legend.
I have generated a simplified version based on the example here: http://matplotlib.org/users/legend_guide.html
Here is what I have so far:
import matplotlib.pyplot as plt
import pylab
fig, ax1 = plt.subplots()
fig.set_size_inches(18/1.5, 10/1.5)
ax2 = ax1.twinx()
ax1.plot([1,2,3], label="Line 1", linestyle='--')
ax2.plot([3,2,1], label="Line 2", linewidth=4)
ax1.legend(loc=2, borderaxespad=1.)
ax2.legend(loc=1, borderaxespad=1.)
pylab.savefig('test.png',bbox_inches='tight', dpi=300, facecolor='w', edgecolor='k')
With the result being the following plot:
As shown in the plot, the data from ax2 is being plotted over the ax1 legend and I would like the legend to be over the top of the data. What am I missing here?
Thanks for the help.
You could replace your legend setting lines with these:
ax1.legend(loc=1, borderaxespad=1.).set_zorder(2)
ax2.legend(loc=2, borderaxespad=1.).set_zorder(2)
And it should do the trick.
Note that locations have changed to correspond to the lines and there is .set_zorder() method applied after the legend is defined.
The higher integer in zorder the 'higher' layer it will be painted on.
The trick is to draw your first legend, remove it, and then redraw it on the second axis with add_artist():
legend_1 = ax1.legend(loc=2, borderaxespad=1.)
legend_1.remove()
ax2.legend(loc=1, borderaxespad=1.)
ax2.add_artist(legend_1)
Tribute to #ImportanceOfBeingErnest :
https://github.com/matplotlib/matplotlib/issues/3706#issuecomment-378407795