ลดระยะขอบซ้ายและขวาในพล็อต matplotlib


178

ฉันพยายามที่จะจัดการกับระยะขอบของฉันใน matplotlib ฉันใช้รหัสด้านล่างเพื่อจัดทำแผนภูมิของฉัน:

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

อย่างไรก็ตามฉันได้รับผลลัพธ์ที่มีพื้นที่สีขาวมากมายทั้งสองข้างของพล็อต ฉันค้นหา google และอ่านเอกสาร matplotlib แต่ฉันไม่สามารถหาวิธีลดได้


ปัญหาคือปริมาณของช่องว่างในextentของimshowตัวเลขหรือปริมาณของช่องว่างชายแดนใน PNG ผลรอบรูปที่สร้างขึ้นโดยsavefig?
unutbu

ฉันคิดว่าทั้งคู่ - ดูเหมือนว่าจะมีพื้นที่มากมายทั้งในหน้าต่างการดูและใน PNG อย่างไรก็ตามเอาต์พุตสำคัญคือไฟล์ png ที่สร้างโดยsavefig- นั่นคือสิ่งที่ฉันต้องการเรียงลำดับ
robintw

ฉันเพิ่งตัดมันใน GIMP หลังจากนั้น : /
endolith

คำตอบ:


251

วิธีหนึ่งที่จะทำเช่นนี้โดยอัตโนมัติเป็น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')

5
มีวิธีใดที่จะทำให้สิ่งนี้เป็นค่าเริ่มต้นหรือไม่
endolith

1
หากคุณมีหลาย subplots และต้องการบันทึกแต่ละอันคุณสามารถใช้มันได้fig.savefig()เช่นกัน ( plt.savefig()จะไม่ทำงานในกรณีนั้น)
Abhranil Das

1
สิ่งทั้งหมดนี้เป็นการครอบตัดรูปภาพหลังจากที่ถูกเรนเดอร์แล้ว ถ้าคุณกำลังพยายามที่จะบังคับใช้โดยเฉพาะอย่างยิ่งความละเอียดภาพจะออกมามีขนาดเล็กลง
Detly

5
@detly - อ๋อ นั่นคือสิ่งที่มันทำ (แม้ว่ามันสามารถครอบตัด "ออก" เช่นกันและทำให้ภาพมีขนาดใหญ่ขึ้นเช่นกัน) สำหรับสิ่งที่คุณต้องการ, fig.tight_layout()มีลักษณะที่ ฟังก์ชั่นนั้นไม่มีอยู่เมื่อคำตอบนี้ถูกเขียนขึ้นมิฉะนั้นฉันจะพูดถึงมันอย่างเด่นชัด
Joe Kington

2
หากใครมีปัญหาให้ใช้fig = plt.gcf()
KyungHoon Kim

148

คุณสามารถปรับระยะห่างรอบตัวเลข matplotlib โดยใช้ฟังก์ชัน 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)

สิ่งนี้จะใช้ได้กับทั้งตัวเลขบนหน้าจอและบันทึกเป็นไฟล์และเป็นฟังก์ชันที่เหมาะสมในการโทรถึงแม้ว่าคุณจะไม่ได้มีหลายแปลงในรูปเดียว

ตัวเลขเป็นเศษส่วนของขนาดภาพและจะต้องมีการปรับเปลี่ยนเพื่อให้สามารถใช้กับป้ายกำกับรูปได้


8
ค่าที่กำหนดให้กับพารามิเตอร์และไม่เปลี่ยนแปลงจำนวนค่าเหล่านี้คือตำแหน่งที่จะตั้งค่าระยะขอบ กล่าวอีกนัยหนึ่งถ้าคุณต้องการให้ค่ามาร์จิ้นขอบขวาเป็น 10% คุณควรตั้งค่า right = 0.9 ไม่ใช่ right = 0.1 matplotlib.sourceforge.net/api/
จิ้น

1
มันสมเหตุสมผลแล้วที่จะชี้ให้เห็นว่าคุณสามารถระบุค่าลบได้ใน plt.subplots_adjust () การทำเช่นนั้นยังช่วยให้คุณสามารถวาดนอกพื้นที่รูปและจัดการกับระยะขอบที่น่ารำคาญ
surchs

สิ่งนี้ใช้ได้กับGridSpecวัตถุด้วยการเรียกใช้updateเมธอด (ดูstackoverflow.com/a/20058199/1030876 )
Aaron Voelker

57

สิ่งที่คุณต้องการคือ

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

7
ฉันคิดว่านี่เป็นวิธีที่ดีที่สุดจริงๆ ไม่จำเป็นต้องบันทึกตัวเลขเช่น `bbox = 'tight' และแก้ไขปัญหาเลย์เอาต์อื่น ๆ ทุกชนิดในรูปแบบที่แออัด
dshepherd

2
นี่ควรเป็นคำตอบที่ถูกต้องเพราะมันจะทำงานได้ตามที่คุณคาดหวังเพราะมันใช้กับภาพแทนภาพ
Majid alDosari

น่าแปลกที่นี่เปลี่ยนความกว้างของพล็อตจริง (เช่นยอดเขาอยู่ใกล้กัน) เมื่อเทียบกับbbox_inches='tight'ซึ่งเพิ่งคลิปพื้นที่สีขาวรอบ ๆ ขอบ แต่ทิ้งพล็อตเพียงอย่างเดียว plt.figure(figsize=(10,3))ฉันสร้างรูปด้วย
Fritz

9

เพียงใช้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])

6

ในกรณีที่ทุกคนสงสัยว่าจะกำจัดขอบสีขาวที่เหลือหลังจากใช้งานplt.tight_layout()หรือfig.tight_layout(): ด้วยพารามิเตอร์pad(ซึ่ง1.08โดยค่าเริ่มต้น) คุณสามารถทำให้แน่นยิ่งขึ้น: "การเว้นระหว่างขอบรูปและขอบของ แบบย่อยเป็นเศษส่วนของขนาดตัวอักษร " ตัวอย่างเช่น

plt.tight_layout(pad=0.05)

จะลดขนาดเหลือเล็กมาก การวาง0ไม่ได้ผลสำหรับฉันเพราะมันทำให้กล่องของแผนย่อยถูกตัดออกไปเล็กน้อยเช่นกัน


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

1
"pad_inches = -1" ทำให้ savefig ของฉันสร้างเฉพาะส่วนของตัวเลขเท่านั้น
Yu Shen

การใช้พารามิเตอร์ในsavefigฟังก์ชั่นนั้นสวยงาม แต่ค่าลบสำหรับpad_inchesนั้นไม่จำเป็นในทุกกรณี
MichaelHuelsen

กำหนดเป็น 0 ช่วย
Joop

4

ปัญหาของ matplotlibs subplots_adjust คือค่าที่คุณป้อนนั้นสัมพันธ์กับ x และ y figsize ของตัวเลข ตัวอย่างนี้ใช้สำหรับการกำหนดขนาดให้ถูกต้องสำหรับการพิมพ์ 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)

สำหรับรูปของ 'figure.xsize' นิ้วใน x-dimension และ 'figure.ysize' in-y ดังนั้นรูปทั้งหมดจึงมีระยะขอบซ้าย 5 มม. ขอบล่าง 4 มม. ขวา 1 มม. และด้านบน 3 มม. ภายในฉลาก การแปลงของ (x / 25.4) เสร็จแล้วเพราะฉันต้องการแปลงมิลลิเมตรเป็นนิ้ว

โปรดทราบว่าขนาดแผนภูมิบริสุทธิ์ของ x จะเป็น "รูป. xsize - ระยะขอบซ้าย - ระยะขอบขวา" และขนาดแผนภูมิบริสุทธิ์ของ y จะเป็น "รูปขนาด. - ขอบด้านล่าง - ระยะขอบด้านบน" ในนิ้ว

sniplets อื่น ๆ (ไม่แน่ใจเกี่ยวกับสิ่งเหล่านี้ฉันแค่ต้องการให้พารามิเตอร์อื่น ๆ )

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

และ

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

3
ในกรณีที่คุณไม่ได้รับxsizeและysizeจาก ฉันใช้คุณสมบัติเหล่านั้นและฉันจะได้AttributeError: 'Figure' object has no attribute 'xsize'
cj5

4

แรงบันดาลใจจากคำตอบของ Sammys ด้านบน:

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 คือ tuple ที่คุณใช้ fig = pyplot.figure(figsize=...)


2

สำหรับฉันคำตอบข้างต้นไม่สามารถใช้กับmatplotlib.__version__ = 1.4.3Win7 ได้ ดังนั้นถ้าเรามีความสนใจเฉพาะในภาพตัวเอง (เช่นถ้าเราไม่จำเป็นต้องใช้คำอธิบายประกอบแกนเห็บชื่อ ylabel ฯลฯ ) แล้วมันจะดีกว่าที่จะเพียงแค่บันทึกอาร์เรย์ numpy 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


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.