मैं matplotlib में पहलू अनुपात कैसे निर्धारित कर सकता हूं?


108

मैं एक वर्ग प्लॉट (imshow का उपयोग करके) बनाने की कोशिश कर रहा हूं, अर्थात 1: 1 का पहलू अनुपात, लेकिन मैं नहीं कर सकता। इनमें से कोई काम नहीं:

import matplotlib.pyplot as plt

ax = fig.add_subplot(111,aspect='equal')
ax = fig.add_subplot(111,aspect=1.0)
ax.set_aspect('equal')
plt.axes().set_aspect('equal')

ऐसा लगता है कि कॉल को केवल अनदेखा किया जा रहा है (एक समस्या जो मुझे अक्सर मैटलपोटलिब के साथ लगती है)।


6
क्या आपने प्रयास किया ax.axis('equal'), संयोग से? जैसा कि सभी ने कहा, आपको क्या करना चाहिए, लेकिन ax.axisवर्कअराउंड के लिए प्रयास करने के लिए एक और मार्ग हो सकता है।
जो किंग्सटन

जवाबों:


77

तीसरी बार आकर्षण। मेरा अनुमान है कि यह एक बग है और जेन्या का उत्तर बताता है कि यह नवीनतम संस्करण में तय किया गया है। मेरे पास संस्करण 0.99.1.1 है और मैंने निम्नलिखित समाधान बनाया है:

import matplotlib.pyplot as plt
import numpy as np

def forceAspect(ax,aspect=1):
    im = ax.get_images()
    extent =  im[0].get_extent()
    ax.set_aspect(abs((extent[1]-extent[0])/(extent[3]-extent[2]))/aspect)

data = np.random.rand(10,20)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data)
ax.set_xlabel('xlabel')
ax.set_aspect(2)
fig.savefig('equal.png')
ax.set_aspect('auto')
fig.savefig('auto.png')
forceAspect(ax,aspect=1)
fig.savefig('force.png')

यह 'बल.पिंग' है: यहां छवि विवरण दर्ज करें

नीचे मेरे असफल, अभी तक उम्मीद से जानकारीपूर्ण प्रयास हैं।

दूसरा उत्तर:

नीचे मेरा 'मूल उत्तर' ओवरकिल है, क्योंकि यह कुछ ऐसा ही करता है axes.set_aspect()। मुझे लगता है कि आप उपयोग करना चाहते हैं axes.set_aspect('auto')। मुझे समझ में नहीं आता कि यह मामला क्यों है, लेकिन यह मेरे लिए एक स्क्वायर इमेज प्लॉट तैयार करता है, उदाहरण के लिए यह स्क्रिप्ट:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.rand(10,20)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(data)
ax.set_aspect('equal')
fig.savefig('equal.png')
ax.set_aspect('auto')
fig.savefig('auto.png')

'समान' पहलू अनुपात के साथ एक छवि भूखंड का निर्माण करता है: यहां छवि विवरण दर्ज करें और 'ऑटो' पहलू अनुपात के साथ: यहां छवि विवरण दर्ज करें

'मूल उत्तर' में नीचे दिया गया कोड स्पष्ट रूप से नियंत्रित पहलू अनुपात के लिए एक प्रारंभिक बिंदु प्रदान करता है, लेकिन एक बार इमोशो कहलाने के बाद इसे नजरअंदाज कर दिया जाता है।

मूल उत्तर:

यहां एक रूटीन का उदाहरण दिया गया है जो सबप्लॉट मापदंडों को समायोजित करेगा ताकि आपको वांछित पहलू अनुपात मिल सके:

import matplotlib.pyplot as plt

def adjustFigAspect(fig,aspect=1):
    '''
    Adjust the subplot parameters so that the figure has the correct
    aspect ratio.
    '''
    xsize,ysize = fig.get_size_inches()
    minsize = min(xsize,ysize)
    xlim = .4*minsize/xsize
    ylim = .4*minsize/ysize
    if aspect < 1:
        xlim *= aspect
    else:
        ylim /= aspect
    fig.subplots_adjust(left=.5-xlim,
                        right=.5+xlim,
                        bottom=.5-ylim,
                        top=.5+ylim)

fig = plt.figure()
adjustFigAspect(fig,aspect=.5)
ax = fig.add_subplot(111)
ax.plot(range(10),range(10))

fig.savefig('axAspect.png')

यह इस तरह एक आंकड़ा पैदा करता है: यहां छवि विवरण दर्ज करें

मैं कल्पना कर सकता हूं कि यदि आपके आंकड़े के भीतर कई सबप्लॉट हैं, तो आप प्रदान किए गए रूटीन में y और x सबप्लॉट की संख्या को कीवर्ड पैरामीटर (प्रत्येक में डिफ़ॉल्ट रूप से 1) में शामिल करना चाहते हैं। तो फिर उन संख्याओं और का उपयोग कर hspaceऔर wspaceकीवर्ड, आप सभी subplots सही पहलू अनुपात बना सकते हैं।


1
ऐसे मामलों के लिए जहां get_imagesएक खाली सूची है (जैसा कि ax.plot([0,1],[0,2])आपके साथ होगा , आप उपयोग कर सकते हैं get_xlimऔरget_ylim
जोएल

यह मुझे लगता है कि अगर लॉगस्केल के साथ यह काम नहीं करेगा। मैंने एक उत्तर जोड़ा है जो इसके लिए परीक्षण करता है और इसे संभालता है। बेझिझक अपने जवाब में शामिल करें और फिर मैं अपना निकाल दूंगा।
जोएल

1
पहलू असमान दिखने का कारण यह है कि समान पहलू का अर्थ है कि x में दृश्य दूरी y के समान होगी। यदि छवि वर्गाकार है, लेकिन प्लॉट dx और डाई अलग हैं, तो वह 1: 1 पहलू अनुपात नहीं है। पहलू अनुपात उस मामले में डाई / डीएक्स होगा।
बर्ट क्यूब्रिक

22

आप कौन सा matplotlibसंस्करण चला रहे हैं? मुझे हाल ही में अपग्रेड करना पड़ा है 1.1.0, और इसके साथ, add_subplot(111,aspect='equal')मेरे लिए काम करता है।


1
matplotlibसंस्करण में मेरे लिए अच्छी तरह से काम करता है 2.0.2jupyter notebookसंस्करण 5.0.0। धन्यवाद।
सतीश

5

उपरोक्त उत्तरों के साथ कई वर्षों की सफलता के बाद, मैंने पाया है कि यह फिर से काम नहीं करेगा - लेकिन मुझे सबप्लॉट्स के लिए एक काम करने का हल मिला

https://jdhao.github.io/2017/06/03/change-aspect-ratio-in-mpl

ऊपर लेखक को पाठ्यक्रम का पूरा श्रेय (जो शायद यहां पोस्ट कर सकते हैं), संबंधित लाइनें हैं:

ratio = 1.0
xleft, xright = ax.get_xlim()
ybottom, ytop = ax.get_ylim()
ax.set_aspect(abs((xright-xleft)/(ybottom-ytop))*ratio)

लिंक में matplotlib द्वारा उपयोग किए जाने वाले विभिन्न समन्वय प्रणालियों का एक क्रिस्टल स्पष्ट विवरण भी है।

सभी महान उत्तरों के लिए धन्यवाद - विशेष रूप से @ यान का जो विजेता बना रहेगा।


3

आपको अंदाजा लगाना चाहिए। इससे मेरा काम बनता है। डॉक्स से:

निर्दिष्ट पहलू अनुपात के साथ एक आंकड़ा बनाएं। यदि arg एक संख्या है, तो उस पहलू अनुपात का उपयोग करें। > अगर आर्ग एक सरणी है, तो अंजीर एक आंकड़ा के लिए चौड़ाई और ऊंचाई का निर्धारण करेगा जो कि पहलू के संरक्षण के अनुपात को फिट करेगा। इंच में चौड़ाई, ऊंचाई की चौड़ाई वापस आ गई है। एक कुल्हाड़ी के साथ और ऊँचाई के साथ एक कुल्हाड़ी बनाना सुनिश्चित करें, जैसे

उदाहरण का उपयोग:

  # make a figure twice as tall as it is wide
  w, h = figaspect(2.)
  fig = Figure(figsize=(w,h))
  ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
  ax.imshow(A, **kwargs)

  # make a figure with the proper aspect for an array
  A = rand(5,3)
  w, h = figaspect(A)
  fig = Figure(figsize=(w,h))
  ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
  ax.imshow(A, **kwargs)

संपादित करें: मुझे यकीन नहीं है कि आप क्या देख रहे हैं। उपरोक्त कोड कैनवास (भूखंड का आकार) को बदलता है। यदि आप आकृति के matplotlib विंडो का आकार बदलना चाहते हैं, तो उपयोग करें:

In [68]: f = figure(figsize=(5,1))

यह 5x1 (wxh) की विंडो का निर्माण करता है।


इसके लिए धन्यवाद - यह कुछ प्रभाव डालता है, कैनवास के पहलू अनुपात को बदलने में: अधिक विशिष्ट होने के लिए, मुझे स्वयं आकृति के पहलू अनुपात को बदलने की आवश्यकता है, जो निम्नलिखित नहीं करता है (एपोल्स स्वरूपण ..): अंजीर = plt.figure (figsize = (plt.figaspect (2.0)))
jtlz2

3

यह उत्तर यान के उत्तर पर आधारित है। यह रैखिक या लॉग-लॉग भूखंडों के लिए पहलू अनुपात निर्धारित करेगा। यदि कुल्हाड़ियों के लॉग-स्केल हैं, तो परीक्षण करने के लिए मैंने https://stackoverflow.com/a/16290035/2966723 से अतिरिक्त जानकारी का उपयोग किया है ।

def forceAspect(ax,aspect=1):
    #aspect is width/height
    scale_str = ax.get_yaxis().get_scale()
    xmin,xmax = ax.get_xlim()
    ymin,ymax = ax.get_ylim()
    if scale_str=='linear':
        asp = abs((xmax-xmin)/(ymax-ymin))/aspect
    elif scale_str=='log':
        asp = abs((scipy.log(xmax)-scipy.log(xmin))/(scipy.log(ymax)-scipy.log(ymin)))/aspect
    ax.set_aspect(asp)

जाहिर है आप अपने logइच्छित किसी भी संस्करण का उपयोग कर सकते हैं, मैंने उपयोग किया है scipy, लेकिन numpyया mathठीक होना चाहिए।

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