188

Instead of the default "boxed" axis style I want to have only the left and bottom axis, i.e.:

+------+         |
|      |         |
|      |   --->  |
|      |         |
+------+         +-------

This should be easy, but I can't find the necessary options in the docs.

Michael Kuhn
  • 7,585
  • 6
  • 25
  • 26

9 Answers9

231

This is the suggested Matplotlib 3 solution from the official website HERE:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)

ax = plt.subplot(111)
ax.plot(x, y)

# Hide the right and top spines
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)

# Only show ticks on the left and bottom spines
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')

plt.show()

enter image description here

divenex
  • 12,429
  • 9
  • 51
  • 51
  • 2
    This is the better than the accepted answer in newer versions of matplotlib. – ffledgling Nov 26 '16 at 20:59
  • 6
    Additional question for beginners: where can you find this answer based on the Matplotlib API doc? If I go there: https://matplotlib.org/api/axes_api.html I don't see any reference to the `spine` object, and I wouldn't have guessed this keyword. – Eric Burel Jan 23 '19 at 16:46
  • @EricBurel I find the Matplotlib documentation poorly designed. I generally find it easier to understand its API from examples. This is why StackOverflow is so important! I wish the Matplotliob documentation was written with the clear and well-organized approach of Scipy and Numpy. – divenex Aug 17 '20 at 13:09
  • 1
    You can also use `ax.spines.top.set_visible(False)` (dot notation instead of brackets and quotes). `spines[['top', 'right']].set_visible(False)` works too. – David Gilbertson May 30 '22 at 02:13
68

Alternatively, this

def simpleaxis(ax):
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.get_xaxis().tick_bottom()
    ax.get_yaxis().tick_left()

seems to achieve the same effect on an axis without losing rotated label support.

(Matplotlib 1.0.1; solution inspired by this).

timday
  • 24,335
  • 11
  • 80
  • 135
33

[edit] matplotlib in now (2013-10) on version 1.3.0 which includes this

That ability was actually just added, and you need the Subversion version for it. You can see the example code here.

I am just updating to say that there's a better example online now. Still need the Subversion version though, there hasn't been a release with this yet.

[edit] Matplotlib 0.99.0 RC1 was just released, and includes this capability.

Oren
  • 3,637
  • 3
  • 30
  • 58
Autoplectic
  • 7,468
  • 29
  • 30
  • Make sure you read the warning at http://matplotlib.sourceforge.net/mpl_toolkits/axes_grid/users/overview.html about tick-mark support being incomplete before you try and use the above with e.g rotated labels though! – timday Nov 04 '11 at 15:06
  • It looks like it depends on how you construct the axis. The axes generated by ``mpl.subplots`` cannot be used this way? – Stefan van der Walt May 02 '14 at 07:57
  • 8
    The example link is now broken. – mkosmala Apr 16 '16 at 17:37
22

(This is more of an extension comment, in addition to the comprehensive answers here.)


Note that we can hide each of these three elements independently of each other:

  • To hide the border (aka "spine"): ax.set_frame_on(False) or ax.spines['top'].set_visible(False)

  • To hide the ticks: ax.tick_params(top=False)

  • To hide the labels: ax.tick_params(labeltop=False)

Evgeni Sergeev
  • 20,806
  • 16
  • 98
  • 121
17

If you need to remove it from all your plots, you can remove spines in style settings (style sheet or rcParams). E.g:

import matplotlib as mpl

mpl.rcParams['axes.spines.right'] = False
mpl.rcParams['axes.spines.top'] = False

If you want to remove all spines:

mpl.rcParams['axes.spines.left'] = False
mpl.rcParams['axes.spines.right'] = False
mpl.rcParams['axes.spines.top'] = False
mpl.rcParams['axes.spines.bottom'] = False
hhh
  • 1,663
  • 3
  • 25
  • 35
15

Library Seaborn has this built in with function .despine().

Just add:

import seaborn as sns

Now create your graph. And add at the end:

sns.despine()

If you look at some of the default parameter values of the function it removes the top and right spine and keeps the bottom and left spine:

sns.despine(top=True, right=True, left=False, bottom=False)

Check out further documentation here: https://seaborn.pydata.org/generated/seaborn.despine.html

Sander van den Oord
  • 8,735
  • 2
  • 38
  • 70
12

If you don't need ticks and such (e.g. for plotting qualitative illustrations) you could also use this quick workaround:

Make the axis invisible (e.g. with plt.gca().axison = False) and then draw them manually with plt.arrow.

nikow
  • 20,725
  • 7
  • 48
  • 69
  • 1
    this seems to remove the spines but leave the tick marks in place. Any idea how to remove the ticks as well? – Rob Young May 18 '11 at 11:55
  • 2
    @Rob: You are right, I actually used a different solution in the script I was thinking of. I changed my answer, this should now work, but in general the accepted solution above is better. – nikow May 18 '11 at 18:44
3

Another way of doing this in a non-global way is using the matplotlib.pyplot.rc_context context manager, as follows:

with plt.rc_context({
    "axes.spines.right": False,
    "axes.spines.top": False,
}):
    fig, ax = plt.subplots()
    ...
astrojuanlu
  • 5,825
  • 8
  • 39
  • 90
0

In case you want to apply this on a frequent basis, you can also create a style sheet as described here and use these settings:

axes.spines.left:   True
axes.spines.bottom: True
axes.spines.top:    False
axes.spines.right:  False
Dave
  • 125
  • 9