2012-01-23 9 views
27

निम्नलिखित आलेख पढ़ना, मैंने साजिश के बाहर एक किंवदंती डालने में कामयाब रहे।साजिश के बाहर एक पौराणिक कथा के साथ Matplotlib savefig

कोड:

import matplotlib.pyplot as pyplot 

x = [0, 1, 2, 3, 4] 
y = [xx*xx for xx in x] 

fig = pyplot.figure() 
ax = fig.add_subplot(111) 

box = ax.get_position() 
ax.set_position([box.x0, box.y0, box.width*0.8, box.height]) 

ax.plot(x, y) 
leg = ax.legend(['abc'], loc = 'center left', bbox_to_anchor = (1.0, 0.5)) 
#pyplot.show() 

fig.savefig('aaa.png', bbox_inches='tight') 

pyplot.show() प्रदर्शित करता है यह बाहर एक पौराणिक कथा के साथ सही साजिश। लेकिन जब मैं इसे fig.savefig() के साथ फ़ाइल के रूप में सहेजता हूं, तो किंवदंती को छोटा कर दिया जाता है।

कुछ Googling मुझे इस तरह के bbox_extra_artists=[leg.legendPatch] या bbox_extra_artists=[leg]savefig() को जोड़ने के रूप में workarounds पता चलता है, लेकिन न तो काम किया।

ऐसा करने का सही तरीका क्या है? Matplotlib संस्करण 0.9 9.3 है।

धन्यवाद।

+1

(मैं देख रहा हूँ इस पुराने धागा है, लेकिन यह गूगल का पहला सदस्य है) वहाँ एक है savefig के लिए कलाकारों को शामिल करके बेहतर समाधान: http://stackoverflow.com/questions/10101700/moving-matplotlib-legend-outside-of-the-axis-makes-it-cutoff-by-the-figure-box – Alleo

उत्तर

22

समस्या यह है कि जब आप गतिशील रूप से साजिश करते हैं, matplotlib सीमाओं को स्वचालित रूप से आपके सभी ऑब्जेक्ट्स को फिट करने के लिए निर्धारित करता है। जब आप कोई फ़ाइल सहेजते हैं, तो चीजें स्वचालित रूप से नहीं की जा रही हैं, इसलिए आपको को अपने आकृति के आकार, और फिर अपने अक्ष ऑब्जेक्ट के बाध्यकारी बॉक्स को निर्दिष्ट करने की आवश्यकता है।

import matplotlib.pyplot as pyplot 

x = [0, 1, 2, 3, 4] 
y = [xx*xx for xx in x] 

fig = pyplot.figure(figsize=(3,3)) 
ax = fig.add_subplot(111) 

#box = ax.get_position() 
#ax.set_position([0.3, 0.4, box.width*0.3, box.height]) 
# you can set the position manually, with setting left,buttom, witdh, hight of the axis 
# object 
ax.set_position([0.1,0.1,0.5,0.8]) 
ax.plot(x, y) 
leg = ax.legend(['abc'], loc = 'center left', bbox_to_anchor = (1.0, 0.5)) 

fig.savefig('aaa.png') 
+0

धन्यवाद , इसने काम कर दिया। मुझे आशा है कि savefig() के भविष्य के संस्करण pyplot.show() के समान सीमा गणना का समर्थन करेंगे। – niboshi

+1

आप इसे फीचर अनुरोध के रूप में जोड़ सकते हैं, और बीटीडब्ल्यू आप एक बहुत पुराने संस्करण का उपयोग कर रहे हैं ... – Oz123

+0

एमएमएम, आप सही हैं। मैं इसे हालिया एक में अपग्रेड करने पर विचार करूंगा। – niboshi

10

हालांकि इस विधि कथा के साथ काम करता है, ऐसा नहीं है जब वहाँ कई subplots कर रहे हैं और हम एक ही समग्र कथा चाहते figlegend साथ अच्छी तरह से काम कर रहा है: यहां अपने कोड को दूर करने के लिए है। savefig जब भी figendend फसल हो जाती है। अगर किसी ऐसे मामले का सामना करना पड़ता है तो मैंने नीचे अपने अस्थायी समाधान को चिपकाया।

import matplotlib.pyplot as plt 

para = { 
    ## this parameter will indicate the position of 
    ## subplot within figure, but will not be shown 
    ## if using bbox_inches='tight' when saving 
    'figure.subplot.top': 0.5 
} 
#plt.rcParams.update(para) 

fig = plt.figure() 

ax=fig.add_subplot(221) 
## only needed when what to manually control 
## subplot ration 
#ax.set_position([0.1,0.6,0.5, 0.4]) 
ax.plot([1,1,1]) 


ax=fig.add_subplot(222) 
#ax.set_position([0.7,0.6,0.5, 0.4]) 
ax.plot([2,2,2]) 

ax=fig.add_subplot(223) 
#ax.set_position([0.1,0.1,0.5, 0.4]) 
ax.plot([3,3,3]) 


ax=fig.add_subplot(224) 
#ax.set_position([0.7,0.1,0.5, 0.4]) 
p1, = ax.plot([4,4,4]) 
p2, = ax.plot([2,3,2]) 

## figlegend does not work fine with tight bbox 
## the legend always get cropped by this option 
## even add bbox extra will not help 
## had to use legend, and manually adjust it to 
## arbitary position such as (0.3, 2.5) 

## http://matplotlib.org/users/tight_layout_guide.html 
## according to this link, tight layout is only 
## an experimental feature, might not support figlegend 

#lgd = plt.figlend(
lgd = plt.legend(
    [p1,p2], 
    ['a', 'b'], 
    ## by default, legend anchor to axis, but can 
    ## also be anchored to arbitary position 
    ## positions within [1,1] would be within the figure 
    ## all numbers are ratio by default 

    bbox_to_anchor=(-0.1, 2.5), 

    ## loc indicates the position within the figure 
    ## it is defined consistent to the same Matlab function 
    loc='center', 

    ncol=2 
    #mode="expand", 
    #borderaxespad=0. 
    ) 



#plt.show() 

plt.savefig('temp.png', bbox_inches='tight')#, bbox_extra_artist=[lgd]) 
+0

इसके लिए धन्यवाद। क्या आपने इस के लिए एक बग रिपोर्ट सबमिट की है (bbox_extra_artists?)? मुझे आपके जैसे ही एक बहु-अक्ष आकृति और बाहर की धुरी के समान समस्या है। मैं अपनी स्थिति में अपना कामकाज लागू नहीं कर सकता। – CPBL

+0

मैंने किसी भी बग रिपोर्ट को नहीं निकाल दिया है। मुझे यकीन नहीं है कि यह एक बग है या इसे इस तरह डिज़ाइन किया गया है। – Ning

0

तो बाकी सब विफल रहता है, मैं इंकस्केप के सीमांकन बॉक्स सुविधाओं का उपयोग मैं क्या matplotlib के उत्पादन में लगातार कीड़े कहेंगे से निपटने के लिए। आप जीएनयू/लिनक्स चला रहे हैं, बस को बचाने के लिए जो भी matplotlib एक PDF के रूप में आप देता है, और फिर निम्न के लिए भेज

def tightBoundingBoxInkscape(pdffile,use_xvfb=True): 
    """Makes POSIX-specific OS calls. Preferably, have xvfb installed, to avoid any GUI popping up in the background. If it fails anyway, could always resort to use_xvfb=False, which will allow some GUIs to show as they carry out the task 
     pdffile: the path for a PDF file, without its extension 
    """ 
    usexvfb='xvfb-run '*use_xvfb 
    import os 
    assert not pdffile.endswith('.pdf') 
    os.system(""" 
     inkscape -f %(FN)s.pdf -l %(FN)s_tmp.svg 
     inkscape -f %(FN)s_tmp.svg --verb=FitCanvasToDrawing \ 
            --verb=FileSave \ 
            --verb=FileQuit 
     inkscape -f %(FN)s_tmp.svg -A %(FN)s-tightbb.pdf 
"""%{'FN':pdffile}