30

I'm looking to decrease density of tick labels on differing subplot

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from StringIO import StringIO
data = """\
    a   b   c   d
z   54.65   6.27    19.53   4.54
w   -1.27   4.41    11.74   3.06
d   5.51    3.39    22.98   2.29
t   76284.53    -0.20   28394.93    0.28
"""
df = pd.read_csv(StringIO(data), sep='\s+')
gs = gridspec.GridSpec(3, 1,height_ratios=[1,1,4] )
ax0 = plt.subplot(gs[0])
ax1 = plt.subplot(gs[1])
ax2 = plt.subplot(gs[2])
df.plot(kind='bar', ax=ax0,color=('Blue','DeepSkyBlue','Red','DarkOrange'))
df.plot(kind='bar', ax=ax1,color=('Blue','DeepSkyBlue','Red','DarkOrange'))
df.plot(kind='bar', ax=ax2,color=('Blue','DeepSkyBlue','Red','DarkOrange'),rot=45)
ax0.set_ylim(69998, 78000)
ax1.set_ylim(19998, 29998)
ax2.set_ylim(-2, 28)
ax0.legend().set_visible(False)
ax1.legend().set_visible(False)
ax2.legend().set_visible(False)
ax0.spines['bottom'].set_visible(False)
ax1.spines['bottom'].set_visible(False)
ax1.spines['top'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax0.xaxis.set_ticks_position('none')
ax1.xaxis.set_ticks_position('none')
ax0.xaxis.set_label_position('top')
ax1.xaxis.set_label_position('top')
ax0.tick_params(labeltop='off')
ax1.tick_params(labeltop='off', pad=15)
ax2.tick_params(pad=15)
ax2.xaxis.tick_bottom()
d = .015
kwargs = dict(transform=ax0.transAxes, color='k', clip_on=False)
ax0.plot((-d,+d),(-d,+d), **kwargs)
ax0.plot((1-d,1+d),(-d,+d), **kwargs)
kwargs.update(transform=ax1.transAxes)
ax1.plot((-d,+d),(1-d,1+d), **kwargs)
ax1.plot((1-d,1+d),(1-d,1+d), **kwargs)
ax1.plot((-d,+d),(-d,+d), **kwargs)
ax1.plot((1-d,1+d),(-d,+d), **kwargs)
kwargs.update(transform=ax2.transAxes)
ax1.plot((-d,+d),(1-d/4,1+d/4), **kwargs)
ax1.plot((1-d,1+d),(1-d/4,1+d/4), **kwargs)
plt.show()

which results in enter image description here

I would like to decrease tick labels in the two upper subplots. How to do that ? Thanks.

Bonus: 1) how to get rid of the dotted line on y=0 at the basis of the bars? 2) how to get rid of x-trick label between subplot 0 and 1? 3) how to set the back of the plot to transparency? (see the right-bottom broken y-axis line that disappears behind the back of the plot)

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
sol
  • 1,389
  • 3
  • 19
  • 32

4 Answers4

58

A general approach is to tell matplotlib the desired number of ticks:

plt.locator_params(nbins=10)

Edit by comments from @Daniel Power: to change for a single axis (e.g. 'x') on an axis, use:

ax.locator_params(nbins=10, axis='x')
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
  • 2
    to change for a single axis (e.g. x) on an axis, use: ax.locator_params(nbins=10,axis='x') – Daniel Power Aug 31 '16 at 19:37
  • 2
    I am getting a `TypeError: set_params() got an unexpected keyword argument 'nbins'` any idea what is wrong with it? – durbachit Nov 10 '16 at 06:12
  • @durbachit are you calling `set_params()` or `locator_params()`? Could you please send the complete traceback error? – Saullo G. P. Castro Nov 10 '16 at 14:24
  • 2
    Calling locator_params. I can't get the full traceback error, it's too long for a comment. a bit further here: `File "C:\Users\...\AppData\Local\Continuum\Anaconda2\lib\site-packages\matplotlib\axes\_base.py", line 2554, in locator_params self.yaxis.get_major_locator().set_params(**kwargs) TypeError: set_params() got an unexpected keyword argument 'nbins'` – durbachit Nov 11 '16 at 02:08
  • @DmitryKabanov I tested today in matplotlib 2.0.2 and it worked – Saullo G. P. Castro Dec 02 '17 at 10:37
  • @SaulloCastro, agree, it works in matplotlib 2.0.2; have just tested it. – Dmitry Kabanov Dec 06 '17 at 07:25
  • 3
    This doesn't seem to work with log axes (at least using old matplotlib 1.4.3). Is there a workaround or equivalent function for log axes? – Drew Hall Jun 07 '18 at 07:52
  • @DrewHall it would be nice if you could post a question with this specific case (have you tried with newer Matplotlib versions?) – Saullo G. P. Castro Jun 07 '18 at 10:24
42

An improvement over the approach suggestion by Aman is the following:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

# ... plot some things ...

# Find at most 101 ticks on the y-axis at 'nice' locations
max_yticks = 100
yloc = plt.MaxNLocator(max_yticks)
ax.yaxis.set_major_locator(yloc)

plt.show()

Hope this helps.

Community
  • 1
  • 1
dmcdougall
  • 2,456
  • 1
  • 17
  • 15
  • This helped reduce the number of ticks, but now I have the first three ticks rather than the ticks at the correct location. – Olga Botvinnik Oct 09 '13 at 06:40
  • 3
    It looks like a MaxNLocator object can only be used for a single axis. If you reuse the locator for more than one axis with different ticks the final ticks will be used for all axes. – Mike Aug 22 '15 at 00:52
22

You can set the ticks to where you want just like you set the xticks.

import numpy as np
ax0.yaxis.set_ticks(np.arange(70000,80000,2500))

This will create four ticks evenly spaced for your ax0 subplot. You can do something similar for your other subplots.

Aman
  • 45,819
  • 7
  • 35
  • 37
3

In case you are using an array of x-axis values that is not numerical (for example dates), I would advise the following method:

import numpy as np
import matplotlib.pyplot as plt


distance_between_ticks = 10
reduced_xticks = x_arr[np.arange(0, len(x_arr), distance_between_ticks)]
    
fig, ax = plt.subplots()

# plot stuff

ax.set_xticks(reduced_xticks)

The numpy.arange function will generate an array of equally spaced indexes that you then apply to your x-axis array.

Warning: the x_arr array HAS to support such an indexing method (i.e. I would advise making sure that it is a numpy array).

Thomas Di Martino
  • 380
  • 1
  • 4
  • 10