Giảm lề trái và phải trong lô matplotlib


178

Tôi đang vật lộn để đối phó với lợi nhuận cốt truyện của mình trong matplotlib. Tôi đã sử dụng mã dưới đây để tạo biểu đồ của mình:

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

Tuy nhiên, tôi nhận được một con số đầu ra với nhiều khoảng trắng ở hai bên của cốt truyện. Tôi đã tìm kiếm trên google và đọc tài liệu matplotlib, nhưng dường như tôi không thể tìm ra cách giảm thứ này.


Là vấn đề số lượng khoảng trắng trong extentcủa imshownhân vật, hoặc số lượng khoảng trắng biên giới trong png kết quả, quanh hình, được tạo ra bởi savefig?
unutbu

Tôi nghĩ cả hai - dường như có rất nhiều không gian trong cả cửa sổ xem và trong PNG. Tuy nhiên, đầu ra quan trọng là tệp png được tạo bởi savefig- vì vậy đó là thứ tôi muốn sắp xếp.
robintw

Sau đó tôi đã cắt chúng trong GIMP. : /
endolith

Câu trả lời:


251

Một cách để tự động làm điều này là bbox_inches='tight'kwarg plt.savefig.

Ví dụ

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

Một cách khác là sử dụng 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')

5
Có cách nào để làm điều này mặc định?
endolith

1
Nếu bạn có nhiều ô con và muốn lưu từng ô, bạn cũng có thể sử dụng nó fig.savefig(). ( plt.savefig()sẽ không hoạt động trong trường hợp đó.)
Abhranil Das

1
Tất cả điều này là cắt hình ảnh sau khi nó được hiển thị; nếu bạn đang cố thực thi một độ phân giải cụ thể, hình ảnh sẽ nhỏ hơn .
gièm pha

5
@detly - Đúng. Đó chính xác là những gì nó làm (mặc dù nó cũng có thể cắt "ra" và làm cho hình ảnh lớn hơn). Đối với những gì bạn muốn, hãy xem fig.tight_layout(). Hàm đó không tồn tại khi câu trả lời này ban đầu được viết, nếu không tôi sẽ đề cập đến nó nổi bật hơn.
Joe Kington

2
Nếu ai đó có vấn đề, hãy sử dụngfig = plt.gcf()
KyungHoon Kim 24/2/2015

148

Bạn có thể điều chỉnh khoảng cách xung quanh các số liệu matplotlib bằng hàm subplots_adjust ():

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

Điều này sẽ hoạt động cho cả hình trên màn hình và được lưu vào một tệp và đó là chức năng phù hợp để gọi ngay cả khi bạn không có nhiều ô trên một hình.

Các số này là các phân số của kích thước hình và sẽ cần được điều chỉnh để cho phép các nhãn hình.


8
Các giá trị được gán cho các tham số và không thay đổi nó bao nhiêu, chúng là nơi đặt lề. Nói cách khác, nếu bạn muốn mang lại lề phải 10%, bạn nên đặt phải = 0,9, không phải = 0,1 matplotlib.sourceforge.net/api/
Lỗi

1
Thật ý nghĩa khi chỉ ra rằng rõ ràng bạn có thể chỉ định các giá trị âm trong plt.subplots_adjust (). Làm như vậy thậm chí cho phép bạn vẽ bên ngoài khu vực hình và cũng để đối phó với các lề khó chịu.
hàng

Điều này cũng hoạt động trên GridSpeccác đối tượng bằng cách gọi updatephương thức (xem stackoverflow.com/a/20058199/1030876 ).
Aaron Voelker

57

Tất cả bạn cần là

plt.tight_layout()

trước đầu ra của bạn.

Ngoài việc cắt giảm lề, điều này cũng nhóm chặt không gian giữa bất kỳ các ô con:

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

7
Tôi nghĩ rằng đây thực sự là phương pháp tốt nhất. Nó không yêu cầu lưu hình như 'bbox =' chặt chẽ 'và khắc phục tất cả các loại vấn đề bố cục khác trong các hình chật chội.
dshepherd

2
đây phải là câu trả lời đúng bởi vì nó hoạt động như bạn mong đợi vì nó áp dụng cho HÌNH thay vì hình ảnh.
Majid alDosari

Thật kỳ lạ, điều này cũng thay đổi độ rộng của âm mưu thực tế (tức là các đỉnh gần nhau hơn) bbox_inches='tight', chỉ cắt các khoảng trắng xung quanh các cạnh nhưng chỉ để lại âm mưu. Tôi đã tạo ra con số với plt.figure(figsize=(10,3)).
Fritz

9

Chỉ cần sử dụng ax = fig.add_axes([left, bottom, width, height]) nếu bạn muốn kiểm soát chính xác bố trí hình. ví dụ.

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

6

Trong trường hợp bất kỳ ai thắc mắc làm thế nào để loại bỏ phần còn lại của lề trắng sau khi áp dụng plt.tight_layout()hoặc fig.tight_layout(): Với tham số pad( 1.08theo mặc định), bạn có thể làm cho nó chặt hơn: "Đệm giữa cạnh hình và các cạnh của các ô phụ, như là một phần của kích thước phông chữ. " Ví dụ

plt.tight_layout(pad=0.05)

sẽ giảm nó xuống một mức rất nhỏ. Đặt 0nó không làm việc cho tôi, vì nó làm cho hộp của subplot cũng bị cắt đi một chút.


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

1
"pad_inches = -1" vì savefig của tôi chỉ tạo ra một phần của hình.
Yu Shen

Sử dụng một tham số trong savefighàm là thanh lịch, tuy nhiên giá trị âm pad_incheskhông nhất thiết cần thiết trong mọi trường hợp.
MichaelHuelsen

đặt nó là 0, giúp
Joop

4

Vấn đề với subplots_adjust của matplotlibs là các giá trị bạn nhập có liên quan đến x và y figsize của hình. Ví dụ này là để định hình chính xác để in pdf:

Vì thế, tôi tính toán lại khoảng cách tương đối với các giá trị tuyệt đối như thế này:

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)

đối với hình 'inch.xsize' inch theo chiều x và 'inch.ysize' inch theo chiều y. Vì vậy, toàn bộ hình có lề trái 5 mm, lề dưới 4 mm, phải 1 mm và đỉnh 3 mm trong nhãn được đặt. Việc chuyển đổi (x / 25.4) được thực hiện vì tôi cần chuyển đổi mm sang inch.

Lưu ý rằng kích thước biểu đồ thuần túy của x sẽ là "hình.xsize - lề trái - lề phải" và kích thước biểu đồ thuần túy của y sẽ là "hình.ysize - lề dưới - lề trên" tính bằng inch

Các sniplets khác (không chắc chắn về những cái này, tôi chỉ muốn cung cấp các tham số khác)

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

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

3
Nơi mà bạn đã nhận được xsizeysizetừ. Tôi sử dụng các thuộc tính đó và tôi nhận đượcAttributeError: 'Figure' object has no attribute 'xsize'
cj5

4

lấy cảm hứng từ câu trả lời của Sammys ở trên:

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)

Trong đó figsize là bộ dữ liệu mà bạn đã sử dụng trong fig = pyplot.figure(figsize=...)


2

Đối với tôi, các câu trả lời ở trên không hoạt động với matplotlib.__version__ = 1.4.3Win7. Vì vậy, nếu chúng ta chỉ quan tâm đến chính hình ảnh (nghĩa là, nếu chúng ta không cần chú thích, trục, đánh dấu, tiêu đề, ylabel, v.v.), thì tốt hơn là chỉ nên lưu mảng numpy như hình ảnh thay vì 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)

Ngoài ra, bằng cách sử dụng các hàm vẽ opencv (cv2.line, cv2.polylines), chúng ta có thể thực hiện một số bản vẽ trực tiếp trên mảng numpy. http://docs.opencv.org/2.4/modules/core/doc/drawing_fifts.html


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.