如何从图形中移除边框

264

要去掉图中的边框,我写下:

frameon=False

使用 pyplot.figure 完美运作,但是使用 matplotlib.Figure 只能去除灰色背景,边框仍然保留。此外,我只希望显示线条,其余部分透明。

使用 pyplot 我可以达到我想要的效果,我希望能够用 matplotlib 实现,不过出于某些长篇原因我宁愿不提及来扩展我的问题。


你能澄清一下你在做什么吗?(例如展示一个例子)你是否使用了 savefig?如果是这样,它会覆盖保存图形时设置的任何内容。手动设置 fig.patch.set_visible(False) 是否有效? - Joe Kington
我使用 canvas.print_png(response) 而不是 savefig。 - Emmet B
11个回答

411

ax.axis('off')会像Joe Kington指出的那样,除了绘制的线条之外,删除所有内容。

对于只想要删除边框(边界),并保留标签、刻度等的人,可以通过访问轴上的spines对象来实现。给定一个轴对象ax,以下内容应该可以删除四个方向的边框:

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

如果需要从图表中移除 xy 刻度线:

Translated:

如果需要从图表中移除 xy 刻度线:

 ax.get_xaxis().set_ticks([])
 ax.get_yaxis().set_ticks([])

4
我喜欢这个方法可以去除图表的上方和右侧边框线。 - Adrian Torrie
6
补充一点:如果还想去掉刻度线: ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom') - JLT
8
如果您还没有轴对象,请使用ax = gca()创建一个轴对象。 - cameronroytaylor
3
这应该是被接受的答案。"ax.axis("off")"会移除所有东西,比如x和y标签、x和y刻度以及图形的所有边框(4个)。为了更好地自定义,每个元素应该分别处理。 - Sanchit
这正是我所需要的。漂亮的图表,我来了。 - EA304GT
ax = gca() 不会创建一个新的坐标轴对象,而是将活动的坐标轴对象分配给变量。因此,是的,它允许您通过该指针访问当前的坐标轴对象。在我看来,这是一个重要的区别。 - undefined

221
首先,如果您正在使用 savefig,请注意,除非您另外指定(例如 fig.savefig('blah.png', transparent=True)),否则它将覆盖图形的背景颜色。
但是,要在屏幕上移除轴和图形的背景,您需要将 ax.patchfig.patch 都设置为不可见。
例如:
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

(当然,在SO的白色背景上你看不出区别,但是一切都是透明的...)
(如果你只想显示线条而不显示其他内容,也可以使用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

在这种情况下,您可能希望使轴占据整个图。如果手动指定轴的位置,则可以告诉它占用整个图(或者,您可以使用subplots_adjust,但对于单个轴的情况,这更简单)。
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


所以这解决了一半的问题。但我也希望这个黑色框架矩形是不可见的。因此,只有蓝线应该是可见的。 - Emmet B
6
那么,如果是这样的话,就更简单了。只需使用ax.axis('off')(您仍然需要关闭图形边框)。 - Joe Kington
谢谢,有没有办法保留刻度标签,例如:我只想要标签 ax.set_yticklabels(('G1', 'G2', 'G3')) - Emmet B
这太棒了,我在另一个应用程序中使用了它:https://dev59.com/bW855IYBdhLWcg3w5InZ#29525514 - cxrodgers
2
在Python 3上,print_png()会抛出一个TypeError: write() argument must be str, not bytes异常。需要将文件以写入二进制('wb')的方式打开才能正常工作。 - Gabriel Jablonski

133

在较新版本的matplotlib中去除丑陋框架的最简单方法:

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

如果您一定要使用面向对象的方法,那么请执行:ax.set_frame_on(False)


7
当使用面向对象的方法时,我使用了ax.set_frame_on(False)来达到同样的效果。或许可以在上面的回答中加入这句话。 - Floyd4K
2
这将删除整个框/矩形,而不仅仅是边框。可能是您想要的,也可能不是。 - getup8
而只隐藏顶部和右侧的线条,解决方案在这里 - mins

71

@peeol的出色回答的基础上,您还可以通过执行以下操作来删除框架

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

举个例子(完整的代码样本可以在此帖子末尾找到),假设你有这样一个柱状图:

enter image description here

你可以使用上面的命令去掉框架,然后保留 xytick 标签(未显示绘图)或同时去除它们。

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

在这种情况下,可以直接标记条形图; 最终的图表可能看起来像这样(代码可以在下面找到):

enter image description here

以下是生成图表所必需的完整代码:

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()

plt.tick_params(top='off') 对我产生了相反的效果。我认为可能应该是 False 而不是 'off' - undefined
1
@drchicken:可能是API已经改变了,这个回答有点老了。稍后会检查并相应地更新 - 感谢你的评论! - undefined
1
谢谢!给你一个赞+1,因为它虽然没有完全按照原文的方式运作,但还是帮我找到了我想要的东西。 - undefined

15

如我在这里所回答的,你可以通过样式设置(样式表或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

13

问题

我在使用axes时遇到了类似的问题。class参数是frameon,但kwarg是frame_onaxes_api
>>> plt.gca().set(frameon=False)
AttributeError: Unknown property frameon

解决方法

frame_on

示例

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()

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')

NameError: name 'client_scripting_ms' is not defined - EA304GT

5

我曾这样做:

from pylab import *
axes(frameon = 0)
...
show()

5
plt.axis('off')
plt.savefig(file_path, bbox_inches="tight", pad_inches = 0)

plt.savefig本身就具有这些选项,在此之前只需要将轴关闭即可


3
plt.box(False)
plt.xticks([])
plt.yticks([])
plt.savefig('fig.png')

应该可以解决问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接