ปรับปรุงขนาด / ระยะห่างของพล็อตย่อยด้วยพล็อตย่อยจำนวนมากใน matplotlib


313

คล้ายกับคำถามนี้มากแต่ด้วยความแตกต่างที่ร่างของฉันอาจมีขนาดใหญ่เท่าที่ควรจะเป็น

ฉันจำเป็นต้องสร้างพล็อตที่ซ้อนกันเป็นแนวตั้งทั้งกลุ่มใน matplotlib ผลลัพธ์จะถูกบันทึกโดยใช้ figsave และดูบนหน้าเว็บดังนั้นฉันไม่สนใจว่าภาพสุดท้ายจะสูงเท่าใดตราบใดที่มีการเว้นระยะย่อยย่อยดังนั้นจึงไม่ทับซ้อนกัน

ไม่ว่าฉันจะยอมให้ร่างใหญ่ขนาดไหนดูเหมือนว่าย่อยจะทับซ้อนกันเสมอ

ขณะนี้รหัสของฉันดูเหมือน

import matplotlib.pyplot as plt
import my_other_module

titles, x_lists, y_lists = my_other_module.get_data()

fig = plt.figure(figsize=(10,60))
for i, y_list in enumerate(y_lists):
    plt.subplot(len(titles), 1, i)
    plt.xlabel("Some X label")
    plt.ylabel("Some Y label")
    plt.title(titles[i])
    plt.plot(x_lists[i],y_list)
fig.savefig('out.png', dpi=100)

คำตอบ:


413

ลองใช้ plt.tight_layout

เป็นตัวอย่างรวดเร็ว:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=4, ncols=4)
fig.tight_layout() # Or equivalently,  "plt.tight_layout()"

plt.show()

ไม่มีเลย์เอาต์แน่น

ป้อนคำอธิบายรูปภาพที่นี่


ด้วยเลย์เอาต์แน่น ป้อนคำอธิบายรูปภาพที่นี่


21
มันต้องการจะเป็นเพียงเล็กน้อยที่ชัดเจนถ้าคุณแสดงให้คุณเห็นควรดำเนินการนี้หลังจากรหัสพล็อตของคุณ แต่ที่เหมาะสมก่อนการแสดง ()
PYJ

5
tight_layout()ถูกตีและพลาด ฉันพยายามที่จะเข้าใจสิ่งที่แตกต่างเมื่อไม่มีผลกระทบ (ระยะขอบระหว่างพล็อตใหญ่ยังคงอยู่) - ซึ่งมักจะเป็น
javadba

3
สิ่งนี้ใช้งานได้ดีสำหรับฉันยกเว้นมันจะซ้อนทับชื่อรูปของฉัน ( suptitle) กับหัวเรื่องย่อยของฉัน ในกรณีที่คนเผชิญหน้าปัญหาที่คล้ายกันนี่คือสิ่งที่ช่วยในกรณีของฉันstackoverflow.com/a/45161551/11740420 กล่าวคือrectพารามิเตอร์ของtight_layout()
Siyana Pavlova

284

คุณสามารถใช้plt.subplots_adjustเพื่อเปลี่ยนระยะห่างระหว่าง subplots (ที่มา)

ลายเซ็นการโทร:

subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

ความหมายของพารามิเตอร์ (และค่าเริ่มต้นที่แนะนำ) คือ:

left  = 0.125  # the left side of the subplots of the figure
right = 0.9    # the right side of the subplots of the figure
bottom = 0.1   # the bottom of the subplots of the figure
top = 0.9      # the top of the subplots of the figure
wspace = 0.2   # the amount of width reserved for blank space between subplots
hspace = 0.2   # the amount of height reserved for white space between subplots

ค่าเริ่มต้นที่เกิดขึ้นจริงจะถูกควบคุมโดยไฟล์ rc


3
ฉันได้ลองยุ่งกับ hspace แต่การเพิ่มมันดูเหมือนว่าจะทำให้กราฟทั้งหมดเล็กลงโดยไม่แก้ไขปัญหาการทับซ้อน ฉันลองเล่นกับพารามิเตอร์อื่น ๆ ด้วย แต่ฉันไม่รู้ว่าซ้าย, ขวา, ล่างและบนกำลังระบุอะไรอยู่
mcstrother

52
@mcstrother คุณสามารถเปลี่ยนแปลงพารามิเตอร์ทั้ง 6 แบบโต้ตอบได้หากคุณคลิกปุ่ม 'การปรับ' หลังจากแสดงพล็อตแล้วคัดลอกลงในรหัสเมื่อคุณพบว่าอะไรทำงาน
Nick T

1
ฉันไม่เห็นปุ่มปรับ แม้ว่าฉันจะอยู่ในสมุดบันทึก Jupyter ฉันลอง% matplotlib แบบอินไลน์และสมุดบันทึก% matplotlib
Matt Kleinsmith

1
@MattKleinsmith: ปุ่มปรับแต่งมีข้อความโฮเวอร์ "Configure subplots" และปรากฏในการใช้งานที่ไม่ใช่โน๊ตบุ๊คปกติของ Matplotlib เป็นปุ่มทางด้านซ้ายของปุ่มบันทึก "ฟลอปปี้ดิสก์" ที่นี่: pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/ … - สังเกตว่าปุ่มนั้นดูแตกต่างกันไปขึ้นอยู่กับระบบหน้าต่างที่คุณใช้ ใช้ แต่มันอยู่ทางด้านซ้ายของปุ่มบันทึก
John Zwinck

@JohnZwinck ลิงก์ในความคิดเห็นของคุณตายแล้ว
user4015990

56

ฉันพบว่า subplots_adjust (hspace = 0.001) เป็นสิ่งที่ทำงานให้ฉัน เมื่อฉันใช้ช่องว่าง = ไม่มีช่องว่างสีขาวยังคงอยู่ระหว่างแต่ละพล็อต การตั้งค่าให้ใกล้กับศูนย์มาก แต่ดูเหมือนว่าจะบังคับให้พวกเขาเข้าแถว สิ่งที่ฉันอัปโหลดที่นี่ไม่ใช่โค้ดที่หรูหราที่สุด แต่คุณสามารถดูว่า hspace ทำงานอย่างไร

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tic

fig = plt.figure()

x = np.arange(100)
y = 3.*np.sin(x*2.*np.pi/100.)

for i in range(5):
    temp = 510 + i
    ax = plt.subplot(temp)
    plt.plot(x,y)
    plt.subplots_adjust(hspace = .001)
    temp = tic.MaxNLocator(3)
    ax.yaxis.set_major_locator(temp)
    ax.set_xticklabels(())
    ax.title.set_visible(False)

plt.show()

ป้อนคำอธิบายรูปภาพที่นี่


31
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,60))
plt.subplots_adjust( ... )

plt.subplots_adjustวิธีการ:

def subplots_adjust(*args, **kwargs):
    """
    call signature::

      subplots_adjust(left=None, bottom=None, right=None, top=None,
                      wspace=None, hspace=None)

    Tune the subplot layout via the
    :class:`matplotlib.figure.SubplotParams` mechanism.  The parameter
    meanings (and suggested defaults) are::

      left  = 0.125  # the left side of the subplots of the figure
      right = 0.9    # the right side of the subplots of the figure
      bottom = 0.1   # the bottom of the subplots of the figure
      top = 0.9      # the top of the subplots of the figure
      wspace = 0.2   # the amount of width reserved for blank space between subplots
      hspace = 0.2   # the amount of height reserved for white space between subplots

    The actual defaults are controlled by the rc file
    """
    fig = gcf()
    fig.subplots_adjust(*args, **kwargs)
    draw_if_interactive()

หรือ

fig = plt.figure(figsize=(10,60))
fig.subplots_adjust( ... )

ขนาดของภาพมีความสำคัญ

"ฉันพยายามทำให้ยุ่งกับ hspace แต่การเพิ่มมันดูเหมือนว่าจะทำให้กราฟทั้งหมดเล็กลงโดยไม่ต้องแก้ไขปัญหาการทับซ้อน"

ดังนั้นเพื่อเพิ่มพื้นที่สีขาวและรักษาขนาดพล็อตย่อยภาพรวมจำเป็นต้องใหญ่ขึ้น


2
ขนาดของรูปภาพมีความสำคัญขนาดของภาพที่ใหญ่กว่าสามารถแก้ปัญหานี้ได้! ตั้งplt.figure(figsize=(10, 7))ขนาดของภาพจะเป็น2000 x 1400pix
Belter


20

คล้ายกับtight_layoutMatplotlib ในขณะนี้ ( ณ วันที่รุ่น 2.2) constrained_layoutให้ ตรงกันข้ามกับtight_layoutซึ่งอาจเรียกได้ว่าเมื่อใดก็ได้ในรหัสสำหรับเลย์เอาต์ที่ปรับปรุงแล้วconstrained_layoutเป็นคุณสมบัติที่อาจใช้งานได้และจะปรับโครงร่างให้เหมาะสมก่อนทุกขั้นตอนการวาด

ดังนั้นจึงจำเป็นต้องเปิดใช้งานก่อนหรือระหว่างการสร้างแผนย่อยเช่นfigure(constrained_layout=True)หรือsubplots(constrained_layout=True)หรือ

ตัวอย่าง:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(4,4, constrained_layout=True)

plt.show()

ป้อนคำอธิบายรูปภาพที่นี่

constrained_layout อาจตั้งค่าเช่นกันผ่าน rcParams

plt.rcParams['figure.constrained_layout.use'] = True

ดูรายการใหม่และคำแนะนำการจัดวางแบบ จำกัด


1
จะลองสิ่งนี้: ไม่เห็นตัวเลือกนี้ - และtight_layoutไม่น่าเชื่อถือ
javadba

สิ่งนี้ฟังดูดี แต่ไม่ให้ระยะห่างพอ (ป้ายและชื่อแกนยังซ้อนทับกัน) และการเรนเดอร์ใช้เวลานานกว่านั้นมาก tight_layout()ทำงานได้ดีขึ้น
craq

2
@craq ที่ถูกต้องโดยทั่วไปcontrained_layoutจะช้าเพราะเท่าที่เห็นในคำตอบนี้ก็optimzes รูปแบบก่อนขั้นตอนการวาดภาพทุก
ImportanceOfBeingErnest

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