Gridlines that overlap with axes spines have different width from other gridlines - python

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.

Related

How i can delete xlabel of plot? [duplicate]

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

Matplotlib: Grid lines behind bars on twinned axes?

I'm plotting two series on one chart using twiny() and want the grid lines behind the bars. However, by default the behaviour is mixed: in front of elements of the original axes and behind the twin's.
Neither axes.set_axisbelow(True) nor zorder=0 with the grid call fixes this. Is this a bug in matplotlib? Anyone know of a work around?
Here's an example to illustrate:
import matplotlib, matplotlib.pyplot as plt
print('matplotlib: {}'.format(matplotlib.__version__))
series1 = [1.25,2.25,3]
series2 = [12,9.75,6.75]
categories = ['A','B','C']
fig, axes1 = plt.subplots(nrows=1,ncols=1)
axes2 = axes1.twiny()
axes1.barh(categories, series1, color='red', align='edge', height=-0.4)
axes2.barh(categories, series2, color='blue', align='edge', height=+0.4)
axes1.set_axisbelow(True)
axes2.set_axisbelow(True)
axes1.grid(axis='x')
axes2.grid(axis='x')
plt.show()
matplotlib v. 3.2.2
Everything drawn on one axis (including the grid) is always or completely before or completely behind everything drawn on the other axis. The only solution in your case is to only draw a grid for axes1, removing the call to the grid for the other axis.

Remove text from figure when using dataframe.boxplot(by=...) [duplicate]

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

matplotlib scatter plot change distance in x-axis

I want to plot some Data with Matplotlib scatter plot.
I used the following code to plot the Data as a scatter with using the same axes for the different subplots.
import numpy as np
import matplotlib.pyplot as plt
epsilon= np.array([1,2,3,4,5])
f, (ax1, ax2, ax3, ax4) = plt.subplots(4, sharex= True, sharey=True)
ax1.scatter(epsilon, mean_percent_100_0, color='r', label='Totaldehnung= 0.000')
ax1.scatter(epsilon, mean_percent_100_03, color='g',label='Totaldehnung= 0.003')
ax1.scatter(epsilon, mean_percent_100_05, color='b',label='Totaldehnung= 0.005')
ax1.set_title('TOR_R')
ax2.scatter(epsilon, mean_percent_111_0,color='r')
ax2.scatter(epsilon, mean_percent_111_03,color='g')
ax2.scatter(epsilon, mean_percent_111_05,color='b')
ax3.scatter(epsilon, mean_percent_110_0,color='r')
ax3.scatter(epsilon, mean_percent_110_03,color='g')
ax3.scatter(epsilon, mean_percent_110_05,color='b')
ax4.scatter(epsilon, mean_percent_234_0,color='r')
ax4.scatter(epsilon, mean_percent_234_03,color='g')
ax4.scatter(epsilon, mean_percent_234_05,color='b')
# Fine-tune figure; make subplots close to each other and hide x ticks for
# all but bottom plot.
f.subplots_adjust(hspace=0.13)
plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
plt.locator_params(axis = 'y', nbins = 4)
ax1.grid()
ax2.grid()
ax3.grid()
ax4.grid()
plt.show()
Now i want to have a x-axis with smaller space between each point. I tried to change the range but it was not working. Can someone help me?
To make the x ticks come closer you might have to set the dimensions of the figure.
Since, in your case, the figure is already created, Set the size of the plot using set_size_inches method of the figure object.
This question contains a few other ways to do the same.
Adding the following line before the plt.show()
fig.set_size_inches(2,8)
Gives me this :
Which I hope is what you are trying to do.

autofmt_xdate deletes x-axis labels of all subplots

I use autofmt_xdate to plot long x-axis labels in a readable way. The problem is, when I want to combine different subplots, the x-axis labeling of the other subplots disappears, which I do not appreciate for the leftmost subplot in the figure below (two rows high). Is there a way to prevent autofmt_xdate from quenching the other x-axis labels? Or is there another way to rotate the labels? As you can see I experimented with xticks and "rotate" as well, but the results were not satisfying because the labels were rotated around their center, which resulted in messy labeling.
Script that produces plot below:
from matplotlib import pyplot as plt
from numpy import arange
import numpy
from matplotlib import rc
rc("figure",figsize=(15,10))
#rc('figure.subplot',bottom=0.1,hspace=0.1)
rc("legend",fontsize=16)
fig = plt.figure()
Test_Data = numpy.random.normal(size=20)
fig = plt.figure()
Dimension = (2,3)
plt.subplot2grid(Dimension, (0,0),rowspan=2)
plt.plot(Test_Data)
plt.subplot2grid(Dimension, (0,1),colspan=2)
for i,j in zip(Test_Data,arange(len(Test_Data))):
plt.bar(i,j)
plt.legend(arange(len(Test_Data)))
plt.subplot2grid(Dimension, (1,1),colspan=2)
xticks = [r"%s (%i)" % (a,b) for a,b in zip(Test_Data,Test_Data)]
plt.xticks(arange(len(Test_Data)),xticks)
fig.autofmt_xdate()
plt.ylabel(r'$Some Latex Formula/Divided by some Latex Formula$',fontsize=14)
plt.plot(Test_Data)
#plt.setp(plt.xticks()[1],rotation=30)
plt.tight_layout()
#plt.show()
This is actually a feature of the autofmt_xdate method. From the documentation of the autofmt_xdate method:
Date ticklabels often overlap, so it is useful to rotate them and right align them. Also, a common use case is a number of subplots with shared xaxes where the x-axis is date data. The ticklabels are often long, and it helps to rotate them on the bottom subplot and turn them off on other subplots, as well as turn off xlabels.
If you want to rotate the xticklabels of the bottom right subplot only, use
plt.setp(plt.xticks()[1], rotation=30, ha='right') # ha is the same as horizontalalignment
This rotates the ticklabels 30 degrees and right aligns them (same result as when using autofmt_xdate) for the bottom right subplot, leaving the two other subplots unchanged.

Categories