How to remove frame from a figure
Asked Answered
J

12

265

To remove frame in figure, I write

frameon=False

works perfect with pyplot.figure, but with matplotlib.Figure it only removes the gray background, the frame stays. Also, I only want the lines to show, and all the rest of figure be transparent.

with pyplot I can do what I want, I want to do it with matplotlib for some long reason I'd rather not mention to extend my question.

Joker answered 16/2, 2013 at 8:49 Comment(2)
Can you clarify what you're doing? (i.e. show an example) Are you using savefig? (If so, it overrides whatever you set when saving the figure.) Does manually setting fig.patch.set_visible(False) work?Diorio
I use canvas.print_png(response), not savefig.Joker
D
222

First off, if you're using savefig, be aware that it will override the figure's background color when saving unless you specify otherwise (e.g. fig.savefig('blah.png', transparent=True)).

However, to remove the axes' and figure's background on-screen, you'll need to set both ax.patch and fig.patch to be invisible.

E.g.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))

for item in [fig, ax]:
    item.patch.set_visible(False)

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

enter image description here

(Of course, you can't tell the difference on SO's white background, but everything is transparent...)

If you don't want to show anything other than the line, turn the axis off as well using ax.axis('off'):

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))

fig.patch.set_visible(False)
ax.axis('off')

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

enter image description here

In that case, though, you may want to make the axes take up the full figure. If you manually specify the location of the axes, you can tell it to take up the full figure (alternately, you can use subplots_adjust, but this is simpler for the case of a single axes).

import matplotlib.pyplot as plt

fig = plt.figure(frameon=False)
ax = fig.add_axes([0, 0, 1, 1])
ax.axis('off')

ax.plot(range(10))

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

enter image description here

Diorio answered 16/2, 2013 at 18:3 Comment(5)
so this solves half the problem. But I also want this black frame rectangle to be invisible. So only the blue line should be visible.Joker
Oh, well, in that case it's even simpler. Just use ax.axis('off') (you'll still need to turn the figure frame off as well).Diorio
thanks, is there a way to keep ticklabels, such as: I want only labels ax.set_yticklabels(('G1', 'G2', 'G3'))Joker
This is great, I used it for another application here: #4093427Uncompromising
The print_png() throws a TypeError: write() argument must be str, not bytes exception for me on python 3. Opening the file as write binary ('wb') is needed for it to work.Appulse
R
424

ax.axis('off'), will as Joe Kington pointed out, remove everything except the plotted line.

For those wanting to only remove the frame (border), and keep labels, tickers etc, one can do that by accessing the spines object on the axis. Given an axis object ax, the following should remove borders on all four sides:

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)

And, in case of removing x and y ticks from the plot:

 ax.get_xaxis().set_ticks([])
 ax.get_yaxis().set_ticks([])
Rudy answered 25/2, 2015 at 13:22 Comment(4)
Just to add: When you also want to remove the ticks: ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom')Still
Also, use ax=gca() to create an axis object if you don't already have one.Macule
This should be the accepted answer. "ax.axis("off")" removes everything like: x and y labels, x and y ticks and all (4) borders from the plot. For better customisation, each element should be handled differently.Polyurethane
ax=gca() does not create a new axis object it assigns the active one to the variable. so yes, it allows you to access the current axis object through that pointer. IMO that is an important distinction.Dearly
D
222

First off, if you're using savefig, be aware that it will override the figure's background color when saving unless you specify otherwise (e.g. fig.savefig('blah.png', transparent=True)).

However, to remove the axes' and figure's background on-screen, you'll need to set both ax.patch and fig.patch to be invisible.

E.g.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))

for item in [fig, ax]:
    item.patch.set_visible(False)

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

enter image description here

(Of course, you can't tell the difference on SO's white background, but everything is transparent...)

If you don't want to show anything other than the line, turn the axis off as well using ax.axis('off'):

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))

fig.patch.set_visible(False)
ax.axis('off')

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

enter image description here

In that case, though, you may want to make the axes take up the full figure. If you manually specify the location of the axes, you can tell it to take up the full figure (alternately, you can use subplots_adjust, but this is simpler for the case of a single axes).

import matplotlib.pyplot as plt

fig = plt.figure(frameon=False)
ax = fig.add_axes([0, 0, 1, 1])
ax.axis('off')

ax.plot(range(10))

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

enter image description here

Diorio answered 16/2, 2013 at 18:3 Comment(5)
so this solves half the problem. But I also want this black frame rectangle to be invisible. So only the blue line should be visible.Joker
Oh, well, in that case it's even simpler. Just use ax.axis('off') (you'll still need to turn the figure frame off as well).Diorio
thanks, is there a way to keep ticklabels, such as: I want only labels ax.set_yticklabels(('G1', 'G2', 'G3'))Joker
This is great, I used it for another application here: #4093427Uncompromising
The print_png() throws a TypeError: write() argument must be str, not bytes exception for me on python 3. Opening the file as write binary ('wb') is needed for it to work.Appulse
B
138

The easiest way to get rid of the ugly frame in newer versions of matplotlib:

import matplotlib.pyplot as plt
plt.box(False)

If you really must always use the object-oriented approach, then do: ax.set_frame_on(False).

Bayern answered 24/9, 2018 at 4:28 Comment(3)
When using the object oriented approach, I had success with ax.set_frame_on(False), which does the same thing. Maybe include in the above answer.Aminta
This removes the entire box/rectangle, not just the frame/borders. May or may not be what you want.Due
And to only hide the top and right lines, the solution is here.Chiao
B
71

Building up on @peeol's excellent answer, you can also remove the frame by doing

for spine in plt.gca().spines.values():
    spine.set_visible(False)

To give an example (the entire code sample can be found at the end of this post), let's say you have a bar plot like this,

enter image description here

you can remove the frame with the commands above and then either keep the x- and ytick labels (plot not shown) or remove them as well doing

plt.tick_params(top='off', bottom='off', left='off', right='off', labelleft='off', labelbottom='on')

In this case, one can then label the bars directly; the final plot could look like this (code can be found below):

enter image description here

Here is the entire code that is necessary to generate the plots:

import matplotlib.pyplot as plt
import numpy as np

plt.figure()

xvals = list('ABCDE')
yvals = np.array(range(1, 6))

position = np.arange(len(xvals))

mybars = plt.bar(position, yvals, align='center', linewidth=0)
plt.xticks(position, xvals)

plt.title('My great data')
# plt.show()

# get rid of the frame
for spine in plt.gca().spines.values():
    spine.set_visible(False)

# plt.show()
# remove all the ticks and directly label each bar with respective value
plt.tick_params(top='off', bottom='off', left='off', right='off', labelleft='off', labelbottom='on')

# plt.show()

# direct label each bar with Y axis values
for bari in mybars:
    height = bari.get_height()
    plt.gca().text(bari.get_x() + bari.get_width()/2, bari.get_height()-0.2, str(int(height)),
                 ha='center', color='white', fontsize=15)
plt.show()
Brahmana answered 11/3, 2017 at 22:4 Comment(3)
plt.tick_params(top='off') is having the opposite effect for me. I think maybe it should be False not 'off'.Cunnilingus
@drchicken: maybe the API has changed; quite an old answer. Will check later and update accordingly - thanks for the comment!Brahmana
Yw! +1 because it led me to what I wanted even though it didn't work exactly as written.Cunnilingus
S
16

As I answered here, you can remove spines from all your plots through style settings (style sheet or rcParams):

import matplotlib as mpl

mpl.rcParams['axes.spines.left'] = False
mpl.rcParams['axes.spines.right'] = False
mpl.rcParams['axes.spines.top'] = False
mpl.rcParams['axes.spines.bottom'] = False
Shoot answered 22/8, 2019 at 22:4 Comment(0)
C
14

Problem

I had a similar problem using axes. The class parameter is frameon but the kwarg is frame_on. axes_api
>>> plt.gca().set(frameon=False)
AttributeError: Unknown property frameon

Solution

frame_on

Example

data = range(100)
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(data)
#ax.set(frameon=False)  # Old
ax.set(frame_on=False)  # New
plt.show()
Capita answered 2/9, 2019 at 11:23 Comment(0)
O
9
df = pd.DataFrame({
'client_scripting_ms' : client_scripting_ms,
 'apimlayer' : apimlayer, 'server' : server
}, index = index)

ax = df.plot(kind = 'barh', 
     stacked = True,
     title = "Chart",
     width = 0.20, 
     align='center', 
     figsize=(7,5))

plt.legend(loc='upper right', frameon=True)

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)

ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('right')
Our answered 22/8, 2019 at 8:53 Comment(1)
NameError: name 'client_scripting_ms' is not definedCorpus
D
6
plt.axis('off')
plt.savefig(file_path, bbox_inches="tight", pad_inches = 0)

plt.savefig has those options in itself, just need to set axes off before

Differentiation answered 19/6, 2020 at 21:39 Comment(0)
M
5

I use to do so:

from pylab import *
axes(frameon = 0)
...
show()
Manvel answered 3/6, 2013 at 12:50 Comment(0)
A
4
plt.box(False)
plt.xticks([])
plt.yticks([])
plt.savefig('fig.png')

should do the trick.

Adin answered 13/4, 2020 at 11:48 Comment(0)
G
2

here is another solution :

img = io.imread(crt_path)

fig = plt.figure()
fig.set_size_inches(img.shape[1]/img.shape[0], 1, forward=False) # normalize the initial size
ax = plt.Axes(fig, [0., 0., 1., 1.]) # remove the edges
ax.set_axis_off() # remove the axis
fig.add_axes(ax)

ax.imshow(img)

plt.savefig(file_name+'.png', dpi=img.shape[0]) # de-normalize to retrieve the original size
Graver answered 12/5, 2021 at 9:44 Comment(0)
L
0

The solution that worked for me (matplotlib 3.8.2) was using argument frameon during the creation of plt.figure to remove white frame around the image (as question argues should work), can see below minimum reproducible code:

import matplotlib.pyplot as plt
import requests
from PIL import Image
img_url = # SOME_URL_FOR_IMAGE
raw_image = Image.open(requests.get(img_url, stream=True).raw).convert("RGB")
plt.figure(figsize=(20,20), frameon=False) # frameon=False solved it
ax = plt.gca()
ax.imshow(raw_image)
plt.axis('off')
plt.show()
Ludovick answered 7/12, 2023 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.