customize ticks label when sharex is on in matplotlib - python

I have two stacked subplots which share the x axis, for both subplots visibility of ticks is set to false because I don't want to see tick labels. after having plotted both subplots, I would like to put some extra ticks on x-asis, only for second subplot, but they don't have to became the main ticks.
I mean, doing this:
#xticks = list of x points
#xlabs = list of labels
#secondplot.set_xticks(xticks)
#secondplot.set_xticklabels(xlabs)
will change the first sublplot grid according to these new ticks as if they became the new major ticks. is there a way to label just some x-axis point in second subplot without affecting the whole plots area? thank you

I know im late to the party but I faced a similar problem and want to share my solution, in case anyone else needs help.
You can use matplotlib.axes.Axes.tick_params to control the style of both major and minor ticks of the axes. Setting the tick lengths of the first subplot to 0 should do the trick:
ax.tick_params(axis="x", which="both", length=0.)
axis ("x", "y" or "both") selects the axes, on which the setting has an effect, which ("major", "minor" or "both") chooses the tick type.
Of course you can then also set major and minor ticks with ax.set_xticks(ticks, minor=False). A full example:
import matplotlib.pyplot as plt
fig, axarr = plt.subplots(2, 1, sharex="col")
axarr[0].plot(range(11))
axarr[1].plot(range(11)[::-1])
axarr[0].tick_params(axis="x", which="both", length=0.)
axarr[1].set_xticks(range(0, 11, 3))
axarr[1].set_xticks(range(0, 11), minor=True)
plt.show()
which yields: https://i.stack.imgur.com/oc7y0.png

This works for removing the tick labels from a single axis when using sharex, but I don't see a solution to also remove the ticks..
import matplotlib.pylab as pl
pl.figure()
ax1=pl.subplot(211)
ax1.plot([0,10],[0,10])
ax2=pl.subplot(212, sharex=ax1)
ax2.plot([0,10],[10,0])
pl.setp(ax1.get_xticklabels(), visible=False)

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

ax.locator_params(nbins=k) does not work in matplotlib

I have this simple piece of code where I try to plot simple graph while limiting number of x ticks. There are hundreds of items in iters variable and if they get plotted it would just create one fat black line.
However, ax.locator_params does not work and the number of ticks aren't reduced.
I have tried setting it on plt object, but no help.
I also tried specifying x and y axes in locator_params, but no help as well.
Finally, I have tried moving ax.locator_params before and after ax.plot, but nothing seemed to help. I am completely out of ideas.
fig, ax = plt.subplots(1, 1, figsize=(20,10))
ax.locator_params(tight=True, nbins=4)
ax.plot(iters, vals)
plt.xticks(rotation=30)
plt.show()
locator_params() with nbins= is only supported for numerical axes where the tick positions are set via MaxNLocator.
To get the same effect with text ticks, the current ticks can be stored in a list (get_xticks) and then be replaced by a subset. Note that changes to ticks (and to limits) should be called after the main plot functions.
xticks = ax.get_xticks()
ax.set_xticks(xticks[::len(xticks) // 4]) # set new tick positions
ax.tick_params(axis='x', rotation=30) # set tick rotation
ax.margins(x=0) # set tight margins

Unable to remove yticks from pyplot subplots

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)

Python Matplotlib: Dual y-axis with same tick spacing and different scale [duplicate]

I created a matplotlib plot that has 2 y-axes. The y-axes have different scales, but I want the ticks and grid to be aligned. I am pulling the data from excel files, so there is no way to know the max limits beforehand. I have tried the following code.
# creates double-y axis
ax2 = ax1.twinx()
locs = ax1.yaxis.get_ticklocs()
ax2.set_yticks(locs)
The problem now is that the ticks on ax2 do not have labels anymore. Can anyone give me a good way to align ticks with different scales?
Aligning the tick locations of two different scales would mean to give up on the nice automatic tick locator and set the ticks to the same positions on the secondary axes as on the original one.
The idea is to establish a relation between the two axes scales using a function and set the ticks of the second axes at the positions of those of the first.
import matplotlib.pyplot as plt
import matplotlib.ticker
fig, ax = plt.subplots()
# creates double-y axis
ax2 = ax.twinx()
ax.plot(range(5), [1,2,3,4,5])
ax2.plot(range(6), [13,17,14,13,16,12])
ax.grid()
l = ax.get_ylim()
l2 = ax2.get_ylim()
f = lambda x : l2[0]+(x-l[0])/(l[1]-l[0])*(l2[1]-l2[0])
ticks = f(ax.get_yticks())
ax2.yaxis.set_major_locator(matplotlib.ticker.FixedLocator(ticks))
plt.show()
Note that this is a solution for the general case and it might result in totally unreadable labels depeding on the use case. If you happen to have more a priori information on the axes range, better solutions may be possible.
Also see this question for a case where automatic tick locations of the first axes is sacrificed for an easier setting of the secondary axes tick locations.
To anyone who's wondering (and for my future reference), the lambda function f in ImportanceofBeingErnest's answer maps the input left tick to a corresponding right tick through:
RHS tick = Bottom RHS tick + (% of LHS range traversed * RHS range)
Refer to this question on tick formatting to truncate decimal places:
from matplotlib.ticker import FormatStrFormatter
ax2.yaxis.set_major_formatter(FormatStrFormatter('%.2f')) # ax2 is the RHS y-axis

Matplotlib: data being plotted over legend when using twinx

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

Categories