减少matplotlib图中的左右边距

问题:减少matplotlib图中的左右边距

我正在努力处理matplotlib中的地块边距。我使用下面的代码来生成图表:

plt.imshow(g)
c = plt.colorbar()
c.set_label("Number of Slabs")
plt.savefig("OutputToUse.png")

但是,我得到了一个在绘图的两边都有很多空白的输出图形。我已经搜索过Google并阅读了matplotlib文档,但似乎找不到如何减少这种情况的方法。

I’m struggling to deal with my plot margins in matplotlib. I’ve used the code below to produce my chart:

plt.imshow(g)
c = plt.colorbar()
c.set_label("Number of Slabs")
plt.savefig("OutputToUse.png")

However, I get an output figure with lots of white space on either side of the plot. I’ve searched google and read the matplotlib documentation, but I can’t seem to find how to reduce this.


回答 0

一种自动执行此操作的方法是使用bbox_inches='tight'kwarg plt.savefig

例如

import matplotlib.pyplot as plt
import numpy as np
data = np.arange(3000).reshape((100,30))
plt.imshow(data)
plt.savefig('test.png', bbox_inches='tight')

另一种方法是使用 fig.tight_layout()

import matplotlib.pyplot as plt
import numpy as np

xs = np.linspace(0, 1, 20); ys = np.sin(xs)

fig = plt.figure()
axes = fig.add_subplot(1,1,1)
axes.plot(xs, ys)

# This should be called after all axes have been added
fig.tight_layout()
fig.savefig('test.png')

One way to automatically do this is the bbox_inches='tight' kwarg to plt.savefig.

E.g.

import matplotlib.pyplot as plt
import numpy as np
data = np.arange(3000).reshape((100,30))
plt.imshow(data)
plt.savefig('test.png', bbox_inches='tight')

Another way is to use fig.tight_layout()

import matplotlib.pyplot as plt
import numpy as np

xs = np.linspace(0, 1, 20); ys = np.sin(xs)

fig = plt.figure()
axes = fig.add_subplot(1,1,1)
axes.plot(xs, ys)

# This should be called after all axes have been added
fig.tight_layout()
fig.savefig('test.png')

回答 1

您可以使用subplots_adjust()函数调整matplotlib图形周围的间距:

import matplotlib.pyplot as plt
plt.plot(whatever)
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)

这将同时适用于屏幕上的图形并保存到文件中,并且即使在一个图形上没有多个图形,这也是调用的正确功能。

数字是图形尺寸的分数,需要进行调整以允许图形标签。

You can adjust the spacing around matplotlib figures using the subplots_adjust() function:

import matplotlib.pyplot as plt
plt.plot(whatever)
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)

This will work for both the figure on screen and saved to a file, and it is the right function to call even if you don’t have multiple plots on the one figure.

The numbers are fractions of the figure dimensions, and will need to be adjusted to allow for the figure labels.


回答 2

所有你需要的是

plt.tight_layout()

在输出之前。

除了减少边距之外,这还将所有子图之间的空间紧密地分组:

x = [1,2,3]
y = [1,4,9]
import matplotlib.pyplot as plt
fig = plt.figure()
subplot1 = fig.add_subplot(121)
subplot1.plot(x,y)
subplot2 = fig.add_subplot(122)
subplot2.plot(y,x)
fig.tight_layout()
plt.show()

All you need is

plt.tight_layout()

before your output.

In addition to cutting down the margins, this also tightly groups the space between any subplots:

x = [1,2,3]
y = [1,4,9]
import matplotlib.pyplot as plt
fig = plt.figure()
subplot1 = fig.add_subplot(121)
subplot1.plot(x,y)
subplot2 = fig.add_subplot(122)
subplot2.plot(y,x)
fig.tight_layout()
plt.show()

回答 3

只要使用ax = fig.add_axes([left, bottom, width, height]) ,如果你想图布局的精确控制。例如。

left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])

Just use ax = fig.add_axes([left, bottom, width, height]) if you want exact control of the figure layout. eg.

left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])

回答 4

如果有人想知道在应用plt.tight_layout()或后如何去除其余的白色边距fig.tight_layout():使用参数pad1.08默认情况下),您可以使其更加紧密:“在图形边缘和子图,仅占字体大小的一部分。” 所以举个例子

plt.tight_layout(pad=0.05)

将其减少到很小的幅度。推杆0对我不起作用,因为它也会使子图的框被剪掉一点。

In case anybody wonders how how to get rid of the rest of the white margin after applying plt.tight_layout() or fig.tight_layout(): With the parameter pad (which is 1.08 by default), you’re able to make it even tighter: “Padding between the figure edge and the edges of subplots, as a fraction of the font size.” So for example

plt.tight_layout(pad=0.05)

will reduce it to a very small margin. Putting 0 doesn’t work for me, as it makes the box of the subplot be cut off a little, too.


回答 5

plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)
plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)

回答 6

matplotlibs subplots_adjust的问题在于,您输入的值相对于图形的x和y图大小。本示例是为了正确打印PDF的图形尺寸:

为此,我将相对间距重新计算为绝对值,如下所示:

pyplot.subplots_adjust(left = (5/25.4)/figure.xsize, bottom = (4/25.4)/figure.ysize, right = 1 - (1/25.4)/figure.xsize, top = 1 - (3/25.4)/figure.ysize)

以x维度表示“ figure.xsize”英寸,以y维度表示“ figure.ysize”英寸。因此,整个标签的左侧边距为5 mm,底部边距为4 mm,右侧边距为1 mm,顶部边距为3 mm。完成(x / 25.4)的转换是因为我需要将mm转换为英寸。

请注意,x的纯图表大小将为“ figure.xsize-左边距-右边距”,y的纯图表大小将为“ figure.ysize-底部边距-顶部边距”(以英寸为单位)

其他代码段(不确定这些代码段,我只想提供其他参数)

pyplot.figure(figsize = figureSize, dpi = None)

pyplot.savefig("outputname.eps", dpi = 100)

The problem with matplotlibs subplots_adjust is that the values you enter are relative to the x and y figsize of the figure. This example is for correct figuresizing for printing of a pdf:

For that, I recalculate the relative spacing to absolute values like this:

pyplot.subplots_adjust(left = (5/25.4)/figure.xsize, bottom = (4/25.4)/figure.ysize, right = 1 - (1/25.4)/figure.xsize, top = 1 - (3/25.4)/figure.ysize)

for a figure of ‘figure.xsize’ inches in x-dimension and ‘figure.ysize’ inches in y-dimension. So the whole figure has a left margin of 5 mm, bottom margin of 4 mm, right of 1 mm and top of 3 mm within the labels are placed. The conversion of (x/25.4) is done because I needed to convert mm to inches.

Note that the pure chart size of x will be “figure.xsize – left margin – right margin” and the pure chart size of y will be “figure.ysize – bottom margin – top margin” in inches

Other sniplets (not sure about these ones, I just wanted to provide the other parameters)

pyplot.figure(figsize = figureSize, dpi = None)

and

pyplot.savefig("outputname.eps", dpi = 100)

回答 7

受以上萨米斯启发的答案:

margins = {  #     vvv margin in inches
    "left"   :     1.5 / figsize[0],
    "bottom" :     0.8 / figsize[1],
    "right"  : 1 - 0.3 / figsize[0],
    "top"    : 1 - 1   / figsize[1]
}
fig.subplots_adjust(**margins)

figsize是您在其中使用的元组 fig = pyplot.figure(figsize=...)

inspired by Sammys answer above:

margins = {  #     vvv margin in inches
    "left"   :     1.5 / figsize[0],
    "bottom" :     0.8 / figsize[1],
    "right"  : 1 - 0.3 / figsize[0],
    "top"    : 1 - 1   / figsize[1]
}
fig.subplots_adjust(**margins)

Where figsize is the tuple that you used in fig = pyplot.figure(figsize=...)


回答 8

对我来说,以上答案matplotlib.__version__ = 1.4.3在Win7上不起作用。因此,如果我们只对图像本身感兴趣(即,如果我们不需要注释,轴,刻度,标题,ylabel等),那么最好将numpy数组另存为image而不是savefig

from pylab import *

ax = subplot(111)
ax.imshow(some_image_numpyarray)
imsave('test.tif', some_image_numpyarray)

# or, if the image came from tiff or png etc
RGBbuffer = ax.get_images()[0].get_array()
imsave('test.tif', RGBbuffer)

另外,使用opencv绘图功能(cv2.line,cv2.polylines),我们可以直接在numpy数组上绘制一些绘图。http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html

For me, the answers above did not work with matplotlib.__version__ = 1.4.3 on Win7. So, if we are only interested in the image itself (i.e., if we don’t need annotations, axis, ticks, title, ylabel etc), then it’s better to simply save the numpy array as image instead of savefig.

from pylab import *

ax = subplot(111)
ax.imshow(some_image_numpyarray)
imsave('test.tif', some_image_numpyarray)

# or, if the image came from tiff or png etc
RGBbuffer = ax.get_images()[0].get_array()
imsave('test.tif', RGBbuffer)

Also, using opencv drawing functions (cv2.line, cv2.polylines), we can do some drawings directly on the numpy array. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html


回答 9

对于最新的matplotlib版本,您可能需要尝试Constrained Layout

With recent matplotlib versions you might want to try Constrained Layout.