Kurangi margin kiri dan kanan di plot matplotlib

178

Saya berjuang untuk berurusan dengan margin plot saya di matplotlib. Saya telah menggunakan kode di bawah ini untuk menghasilkan bagan saya:

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

Namun, saya mendapatkan angka output dengan banyak ruang putih di kedua sisi plot. Saya telah mencari di google dan membaca dokumentasi matplotlib, tetapi sepertinya saya tidak bisa menemukan cara untuk mengurangi ini.

Robintw
sumber
Apakah masalah jumlah spasi dalam extentdari imshowangka, atau jumlah spasi perbatasan di png dihasilkan, sekitar angka, yang dihasilkan oleh savefig?
unutbu
Saya pikir keduanya - sepertinya ada banyak ruang di jendela tampilan dan di PNG. Namun, output penting adalah file png yang diproduksi oleh savefig- jadi itulah yang ingin saya urutkan.
robintw
Saya baru saja memotong mereka di GIMP sesudahnya. : /
endolith

Jawaban:

251

Salah satu cara untuk melakukan ini secara otomatis adalah bbox_inches='tight'kwarg to plt.savefig.

Misalnya

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

Cara lain adalah menggunakan 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')
Joe Kington
sumber
5
Apakah ada cara untuk menjadikan ini default?
endolith
1
Jika Anda memiliki beberapa subplot dan ingin menyimpannya masing-masing, Anda dapat menggunakannya fig.savefig()juga. ( plt.savefig()tidak akan bekerja dalam kasus itu.)
Abhranil Das
1
Semua ini dilakukan adalah memotong gambar setelah gambar dibuat; jika Anda mencoba menerapkan resolusi tertentu, gambar akan keluar lebih kecil .
Detly
5
@detly - Yap. Itulah yang dilakukannya (meskipun dapat memotong "keluar" juga dan membuat gambar lebih besar, juga). Untuk apa yang Anda inginkan, lihatlah fig.tight_layout(). Fungsi itu tidak ada ketika jawaban ini awalnya ditulis, kalau tidak saya akan menyebutkannya lebih jelas.
Joe Kington
2
Jika seseorang memiliki masalah, gunakanfig = plt.gcf()
KyungHoon Kim
148

Anda dapat menyesuaikan spasi di sekitar angka matplotlib menggunakan fungsi 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)

Ini akan berfungsi baik untuk gambar di layar dan disimpan ke file, dan itu adalah fungsi yang tepat untuk memanggil bahkan jika Anda tidak memiliki banyak plot pada satu gambar.

Angka-angka adalah pecahan dari dimensi gambar, dan perlu disesuaikan untuk memungkinkan label gambar.

DaveP
sumber
8
Nilai yang ditetapkan untuk parameter dan bukan seberapa banyak untuk mengubahnya, mereka adalah di mana harus mengatur margin. Dengan kata lain, jika Anda ingin membawa margin tepi kanan sebesar 10%, Anda harus menetapkan kanan = 0,9, tidak benar = 0,1 matplotlib.sourceforge.net/api/…
drootang
1
Masuk akal untuk menunjukkan bahwa Anda jelas dapat menentukan nilai negatif di plt.subplots_adjust (). Melakukannya bahkan memungkinkan Anda untuk menggambar di luar area gambar dan juga untuk berurusan dengan margin yang mengganggu.
surchs
Ini juga berfungsi pada GridSpecobjek dengan memanggil updatemetode (lihat stackoverflow.com/a/20058199/1030876 ).
Aaron Voelker
57

Yang kamu butuhkan adalah

plt.tight_layout()

sebelum hasil Anda.

Selain memotong margin, ini juga secara ketat mengelompokkan ruang di antara setiap subplot:

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()
pengguna2065406
sumber
7
Saya pikir ini adalah metode terbaik. Tidak perlu menyimpan gambar seperti `bbox = 'ketat' dan memperbaiki semua jenis masalah tata letak lainnya dalam angka sempit.
dshepherd
2
ini harus menjadi jawaban yang benar karena berperilaku seperti yang Anda harapkan karena berlaku untuk GAMBAR alih-alih gambar.
Majid alDosari
Anehnya, ini juga mengubah lebar plot sebenarnya (yaitu puncak lebih dekat bersama-sama) dibandingkan dengan bbox_inches='tight', yang hanya memotong ruang putih di sekitar tepi tetapi meninggalkan plot itu sendiri. Saya membuat gambar dengan plt.figure(figsize=(10,3)).
Fritz
9

Cukup gunakan ax = fig.add_axes([left, bottom, width, height]) jika Anda ingin kontrol tata letak gambar yang tepat. misalnya.

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

Jika ada yang bertanya-tanya bagaimana cara menghilangkan sisa margin putih setelah menerapkan plt.tight_layout()atau fig.tight_layout(): Dengan parameter pad(yang secara 1.08default), Anda dapat membuatnya lebih ketat: "Padding antara tepi gambar dan tepi subplot, sebagai sebagian kecil dari ukuran font. " Jadi misalnya

plt.tight_layout(pad=0.05)

akan menguranginya menjadi margin yang sangat kecil. Puting 0tidak berfungsi untuk saya, karena itu membuat kotak subplot sedikit terpotong juga.

Oberwaschlappen
sumber
4
plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)
Tian Chu
sumber
1
"pad_inches = -1" karena savefig saya hanya menghasilkan bagian dari gambar.
Yu Shen
Menggunakan parameter dalam savefigfungsi itu elegan, namun nilai negatif untuk pad_inchestidak selalu diperlukan dalam setiap kasus.
MichaelHuelsen
set ke 0, bantu
Joop
4

Masalah dengan matplotlibs subplots_adjust adalah bahwa nilai yang Anda masukkan relatif terhadap x dan y figsize dari gambar. Contoh ini untuk menentukan angka yang benar untuk pencetakan pdf:

Untuk itu, saya menghitung ulang jarak relatif ke nilai absolut seperti ini:

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)

untuk figur 'figur.xsize' inci dalam dimensi x dan 'figur.isize' inci dalam dimensi-y. Jadi seluruh gambar memiliki margin kiri 5 mm, margin bawah 4 mm, kanan 1 mm dan atas 3 mm di dalam label ditempatkan. Konversi (x / 25,4) dilakukan karena saya perlu mengkonversi mm ke inci.

Perhatikan bahwa ukuran bagan murni x akan menjadi "figure.xsize - margin kiri - margin kanan" dan ukuran bagan murni y akan menjadi "figur.isize - margin bawah - margin atas" dalam inci

Sniplets lain (tidak yakin tentang ini, saya hanya ingin memberikan parameter lain)

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

dan

pyplot.savefig("outputname.eps", dpi = 100)
Sammy
sumber
3
Di mana Anda mendapatkan xsizedan ysizedari. Saya menggunakan properti itu dan saya dapatkanAttributeError: 'Figure' object has no attribute 'xsize'
cj5
4

terinspirasi oleh jawaban Sammys di atas:

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)

Di mana figsize adalah tuple yang Anda gunakan fig = pyplot.figure(figsize=...)

michaelosthege
sumber
2

Bagi saya, jawaban di atas tidak berfungsi matplotlib.__version__ = 1.4.3pada Win7. Jadi, jika kita hanya tertarik pada gambar itu sendiri (yaitu, jika kita tidak memerlukan anotasi, sumbu, kutu, judul, ylabel dll), maka lebih baik hanya menyimpan array numpy sebagai gambar alih-alih 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)

Juga, menggunakan fungsi-fungsi menggambar OpenCV (cv2.line, cv2.polylines), kita dapat melakukan beberapa gambar langsung pada array numpy. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html

otterb
sumber
2

Dengan versi matplotlib terbaru, Anda mungkin ingin mencoba Layout Terkendali .

Michel de Ruiter
sumber