Matplotlib tight_layout () खाता आकृति में नहीं लेता है


207

अगर मैं अपने matplotlib फिगर में एक सबटाइटल जोड़ दूं तो यह सबप्लॉट के टाइटल्स द्वारा ओवरलैड हो जाता है। क्या किसी को पता है कि आसानी से उसकी देखभाल कैसे करें? मैंने tight_layout()फंक्शन की कोशिश की , लेकिन यह केवल चीजों को बदतर बनाता है।

उदाहरण:

import numpy as np
import matplotlib.pyplot as plt

f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.tight_layout()
plt.show()

जवाबों:


178

आप tight_layoutनिम्न में कॉल में सबप्लोट ज्यामिति को समायोजित कर सकते हैं:

fig.tight_layout(rect=[0, 0.03, 1, 0.95])

जैसा कि प्रलेखन में कहा गया है ( https://matplotlib.org/users/tight_layout_guide.html ):

tight_layout()केवल टिकलबल्स, अक्ष लेबल और शीर्षक पर विचार करता है। इस प्रकार, अन्य कलाकारों को क्लिप किया जा सकता है और ओवरलैप भी हो सकता है।


1
यह आकर्षण की तरह काम करता था, लेकिन बाउंडिंग बॉक्स को निर्दिष्ट करते समय परिवर्तन कैसे होता है? मैंने डॉक्टर को पढ़ा लेकिन मुझे बहुत कुछ स्पष्ट नहीं था। यह बहुत अच्छा होगा यदि आप मुझे समझा सकते हैं! धन्यवाद।
thepunitsingh

2
क्या आप कृपया प्रत्येक संख्या का अर्थ बता सकते हैं? मैंने उन्हें डॉक्टर में नहीं देखा।
स्टीवन

6
@ जल्द देखें tight_layoutडॉक्स:[left, bottom, right, top] in normalized (0, 1) figure coordinates
शाम

1
आप सही मूल्य को कम करके, सॉप्टल और कुल्हाड़ियों के बीच की जगह को और अधिक बढ़ा सकते हैं: tight_layout(rect=[0, 0.03, 1, 0.9])इसके बजाय 0.95उत्तर में।
कॉमफ्रीक

1
जुपिटर के अंदर काम नहीं किया। संख्याओं के लिए अलग-अलग मूल्यों की कोशिश की, कोई प्रभाव नहीं पड़ा
UVs Fomins

114

आप मैन्युअल रूप से रिक्ति को समायोजित कर सकते हैं plt.subplots_adjust(top=0.85):

import numpy as np
import matplotlib.pyplot as plt

f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.subplots_adjust(top=0.85)
plt.show()

5
ध्यान दें कि जब आप कॉल करते हैं तो शीर्ष के लिए डिफ़ॉल्ट मान 0.9 हैsubplots_adjust
ब्रायन बर्न्स

72
मैं अपने प्रभु के वर्ष २०१ this में विश्वास नहीं कर सकता यह अभी भी matplotlib का एक बग है।
शब्दफोरवाइज

29
ध्यान दें कि किसी भी कॉल के बाद कॉल subplots_adjustकिया जाना चाहिए , या कॉलिंग का कोई प्रभाव नहीं होगा । tight_layoutsubplots_adjust
अचल दवे

7
@wordsforthewise उस 2018 को अब बनाते हैं
vlsd

6
@vlsd हैलो 2019 से
Xiaoyu Lu

55

एक चीज जिसे आप अपने कोड में बहुत आसानी से बदल सकते हैं, वह यह है कि fontsizeआप शीर्षकों के लिए उपयोग कर रहे हैं। हालाँकि, मैं मान रहा हूँ कि आप ऐसा नहीं करना चाहते हैं!

उपयोग करने के लिए कुछ विकल्प fig.subplots_adjust(top=0.85):

आमतौर पर tight_layout() पर अच्छे स्थानों में सब कुछ स्थिति में एक बहुत अच्छा काम करता है ताकि वे ओवरलैप न हों। कारण tight_layout()इस मामले में मदद नहीं करता है क्योंकि tight_layout()खाते में fig.suptitle () नहीं लेता है। GitHub पर इस बारे में एक खुला समस्या है: https://github.com/matplotlib/matplotlib/issues/829 [वजह से एक पूर्ण ज्यामिति प्रबंधक की आवश्यकता होती है करने के लिए 2014 में बंद कर दिया गया - में स्थानांतरित कर दिया https://github.com/matplotlib/matplotlib / मुद्दों / 1109 ]।

यदि आप थ्रेड पढ़ते हैं, तो आपकी समस्या का समाधान है GridSpec। कुंजी काग के tight_layoutउपयोग से, कॉल करते समय आंकड़े के शीर्ष पर कुछ जगह छोड़ना है rect। आपकी समस्या के लिए, कोड बन जाता है:

ग्रिडस्पेक का उपयोग करना

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

f = np.random.random(100)
g = np.random.random(100)

fig = plt.figure(1)
gs1 = gridspec.GridSpec(1, 2)
ax_list = [fig.add_subplot(ss) for ss in gs1]

ax_list[0].plot(f)
ax_list[0].set_title('Very Long Title 1', fontsize=20)

ax_list[1].plot(g)
ax_list[1].set_title('Very Long Title 2', fontsize=20)

fig.suptitle('Long Suptitle', fontsize=24)    

gs1.tight_layout(fig, rect=[0, 0.03, 1, 0.95])  

plt.show()

परिणाम:

ग्रिडस्पेक का उपयोग करना

हो सकता GridSpecहै कि यह आपके लिए थोड़ा अधिक कठिन हो, या आपकी वास्तविक समस्या में बहुत बड़े कैनवास, या अन्य जटिलताओं पर कई और अधिक सबप्लॉट शामिल होंगे। एक साधारण हैक सिर्फ नकल annotate()करने के 'figure fraction'लिए निर्देशांक का उपयोग और लॉक करना हैsuptitle । हालाँकि आउटपुट पर एक नज़र डालने पर आपको कुछ बेहतर समायोजन करने की आवश्यकता हो सकती है। ध्यान दें कि यह दूसरा समाधान उपयोग नहीं करता है tight_layout()

सरल उपाय (हालांकि ठीक होने की आवश्यकता हो सकती है)

fig = plt.figure(2)

ax1 = plt.subplot(121)
ax1.plot(f)
ax1.set_title('Very Long Title 1', fontsize=20)

ax2 = plt.subplot(122)
ax2.plot(g)
ax2.set_title('Very Long Title 2', fontsize=20)

# fig.suptitle('Long Suptitle', fontsize=24)
# Instead, do a hack by annotating the first axes with the desired 
# string and set the positioning to 'figure fraction'.
fig.get_axes()[0].annotate('Long Suptitle', (0.5, 0.95), 
                            xycoords='figure fraction', ha='center', 
                            fontsize=24
                            )
plt.show()

परिणाम:

सरल

[ Python2.7.3 (64-बिट) और matplotlib1.2.0 का उपयोग करना ]


1
धन्यवाद, अगर मैं आपके द्वारा सुझाए गए पहले समाधान का उपयोग GridSpecकर रहा हूं (उपयोग कर रहा हूं) तो मैं एक्सप्ल्स को साझा करने वाले सबप्लॉट कैसे बना सकता हूं? मैं आमतौर पर plt.subplots(N,1, sharex=<>, sharey=<>)सबप्लॉट बनाते समय उपयोग करता हूं , लेकिन आपके द्वारा पोस्ट किया गया कोड add_subplotइसके बजाय उपयोग करता है
Amelio Vazquez-Reina

10
कास्टिंग fig.tight_layout(rect=[0, 0.03, 1, 0.95])भी काम करती है।
सूपॉल्ट

1
दूसरा समाधान केवल वही है जो मेरे लिए काम करता है। धन्यवाद!
हगबार्ड

19

समाधान का उपयोग करने का एक वैकल्पिक और सरल तरीका यह है कि suptitle के कॉल में y तर्क का उपयोग करके आंकड़े में suptitle पाठ के निर्देशांक समायोजित करें ( डॉक्स देखें ):

import numpy as np
import matplotlib.pyplot as plt

f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', y=1.05, fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.show()

8
यह एक नोटबुक में एक शानदार तरीका है लेकिन plt.savefig () कमांड का पालन नहीं करता है। यह समाधान अभी भी एक savefig कमांड में शीर्षक काट देता है।
सुपरहीरो

11

चुस्त लेआउट के साथ काम नहीं करता है, लेकिन constrained_layoutकरता है। इस प्रश्न को देखें matplotlib में कई सबप्लॉट्स के साथ सबप्लोट आकार / रिक्ति में सुधार करें

मैंने पाया कि सबप्लॉट को एक बार में बेहतर पाया गया था, अर्थात

fig, axs = plt.subplots(rows, cols, constrained_layout=True)

# then iterating over the axes to fill in the plots

लेकिन यह उस बिंदु पर भी जोड़ा जा सकता है जो आंकड़ा बनाया गया है:

fig = plt.figure(constrained_layout=True)

ax1 = fig.add_subplot(cols, rows, 1)
# etc

नोट: मेरे सबप्लॉट्स को एक साथ करीब लाने के लिए, मैं भी उपयोग कर रहा था

fig.subplots_adjust(wspace=0.05)

और विवश_लेआउट इसके साथ काम नहीं करता है :(


4

मैं, matplotlib तरीकों छंटाई के साथ संघर्ष किया है इसलिए मैं अब सिर्फ एक के माध्यम से यह करने के लिए एक समारोह कर दिया है bashकरने के लिए कॉल ImageMagickकी mogrify आदेश है, जो अच्छी तरह से काम करता है और यह आंकड़ा के किनारे से सभी अतिरिक्त सफेद स्थान हो जाता है। इसके लिए आवश्यक है कि आप UNIX / Linux का उपयोग कर रहे हैं, bashशेल का उपयोग कर रहे हैं , और ImageMagickइंस्टॉल कर चुके हैं।

अपने savefig()कॉल के बाद बस एक कॉल फेंक दें ।

def autocrop_img(filename):
    '''Call ImageMagick mogrify from bash to autocrop image'''
    import subprocess
    import os

    cwd, img_name = os.path.split(filename)

    bashcmd = 'mogrify -trim %s' % img_name
    process = subprocess.Popen(bashcmd.split(), stdout=subprocess.PIPE, cwd=cwd)

3

जैसा कि दूसरों द्वारा उल्लेख किया गया है, डिफ़ॉल्ट रूप से तंग लेआउट गुप्त खाते को नहीं लेता है। हालाँकि, मैंने पाया है bbox_extra_artistsकि सॉकेट में पासिंग बॉक्स के रूप में पारित करने के लिए तर्क का उपयोग करना संभव है जिसे निम्न में लिया जाना चाहिए:

st = fig.suptitle("My Super Title")
plt.savefig("figure.png", bbox_extra_artists=[st], bbox_inches='tight')

यह तंग लेआउट गणना को ध्यान में रखने के लिए मजबूर करता है suptitle, और ऐसा लगता है कि आप उम्मीद करेंगे।


यह एकमात्र विकल्प है जिसने मेरे लिए काम किया। मैं आंकड़े बनाने और उन्हें बचाने के लिए ज्यूपिटर नोटबुक का उपयोग करता हूं। मैं लिनक्स मशीन पर अजगर 3.6 में काम करता हूं।
ग्राकांति

2

केवल एक चीज जो मेरे लिए काम करती थी वह कॉल को संशोधित करने के लिए संशोधित कर रही थी:

fig.suptitle("title", y=.995)

1

मेरे पास एक समान मुद्दा था जो tight_layoutबहुत बड़े ग्रिड (200 से अधिक सबप्लॉट) के ग्रिड का उपयोग करते समय और एक ज्यूपिटर नोटबुक में रेंडर करते समय क्रॉप हुआ था। मैंने एक त्वरित समाधान किया जो हमेशा suptitleआपके शीर्ष सबप्लॉट के ऊपर एक निश्चित दूरी पर रखता है :

import matplotlib.pyplot as plt

n_rows = 50
n_col = 4
fig, axs = plt.subplots(n_rows, n_cols)

#make plots ...

# define y position of suptitle to be ~20% of a row above the top row
y_title_pos = axs[0][0].get_position().get_points()[1][1]+(1/n_rows)*0.2
fig.suptitle('My Sup Title', y=y_title_pos)

वेरिएबल-आकार के सबप्लॉट्स के लिए, आप अभी भी इस विधि का उपयोग सबसे ऊपरी सबप्लॉट के शीर्ष को प्राप्त करने के लिए कर सकते हैं, फिर मैन्युअल रूप से एक अतिरिक्त राशि को रूपांतरित करने के लिए जोड़ सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.