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

呼び出しは無視されているようです(matplotlibでよくある問題です)。


6
ax.axis('equal')たまたまやってみましたか?みんなが言ったように、あなたがしたことはうまくいくはずですがax.axis、回避策を試す別のルートかもしれません。
Joe Kington

回答:


77

三回目の魅力。私の推測では、これはバグであり、Zhenyaの回答は最新バージョンで修正されていることを示唆しています。私はバージョン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')

これは「force.png」です。 ここに画像の説明を入力してください

以下は私の失敗ですが、うまくいけば有益な試みです。

2番目の答え:

以下の私の「元の答え」は、と似たようなものなので、やりすぎ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')

「等しい」アスペクト比の画像プロットとここに画像の説明を入力してください 「自動」アスペクト比の画像プロットを作成します 。 ここに画像の説明を入力してください

下記の「元の回答」で提供されるコードは、明示的に制御されたアスペクト比の開始点を提供しますが、imshowが呼び出されると無視されるようです。

元の回答:

希望のアスペクト比が得られるようにサブプロットパラメータを調整するルーチンの例を次に示します。

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キーワードを使用して、すべてのサブプロットに正しいアスペクト比を持たせることができます。


1
get_imagesが空のリストである場合(で発生するようにax.plot([0,1],[0,2])get_xlimand を使用できますget_ylim
Joel

これは、logscaleで実行すると機能しないように見えます。それをテストして処理する回答を追加しました。それを自由に回答に組み込んでください。それから私は削除します。
Joel

1
アスペクトが等しくないように見える理由は、アスペクトが等しいということは、xの視覚距離がyと同じになることを意味するためです。画像が正方形であるが、プロットdxとdyが異なる場合、それは1:1のアスペクト比ではありません。その場合、アスペクト比はdy / dxになります。
バートキュブリッヒ

22

matplotlib実行しているバージョンは何ですか?最近、にアップグレードする必要1.1.0がありましたが、これでadd_subplot(111,aspect='equal')うまくいきました。


1
matplotlibバージョンで私のためにうまくいき2.0.2ます。jupyter notebookバージョン5.0.0。ありがとう。
Sathish

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で使用されるさまざまな座標系の明確な説明もあります。

すばらしい回答をいただきありがとうございます。特に@Yannは引き続き勝者となります。


3

figaspectで試してみてください。わたしにはできる。ドキュメントから:

指定されたアスペクト比で図を作成します。argが数値の場合、そのアスペクト比を使用します。> argが配列の場合、figaspectは、アスペクト比を維持しながら配列に適合する図の幅と高さを決定します。図の幅、インチ単位の高さが返されます。と同じ高さの軸を作成してください。例:

使用例:

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

編集:私はあなたが何を探しているのかわかりません。上記のコードは、キャンバス(プロットサイズ)を変更します。Figureのmatplotlibウィンドウのサイズを変更する場合は、次を使用します。

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

これは5x1(wxh)のウィンドウを生成します。


このおかげで、キャンバスの縦横比を変更することで、ある程度の効果があります。具体的には、図自体の縦横比を変更する必要がありますが、次のことは行いません(apolsの書式設定)。 = 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問題ないはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.