web-dev-qa-db-ja.com

既存の軸のmatplotlibのサブプロット投影を変更するにはどうすればよいですか?

サブプロットインスタンス(_matplotlib.axes._subplots.AxesSubplot_)を取り、その投影を別の投影、たとえば_cartopy.crs.CRS_投影の1つに変換する単純な関数を作成しようとしています。

アイデアはこんな感じ

_import cartopy.crs as ccrs
import matplotlib.pyplot as plt

def make_ax_map(ax, projection=ccrs.PlateCarree()):
    # set ax projection to the specified projection
    ...
    # other fancy formatting
    ax2.coastlines()
    ...

# Create a grid of plots
fig, (ax1, ax2) = plt.subplots(ncols=2)
# the first subplot remains unchanged
ax1.plot(np.random.Rand(10))
# the second one gets another projection
make_ax_map(ax2)
_

もちろん、単にfig.add_subplot()関数を使用できます:

_fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(121)
ax1.plot(np.random.Rand(10))

ax2 = fig.add_subplot(122,projection=ccrs.PlateCarree())
ax2.coastlines()
_

しかし、サブプロット軸の投影を変更する適切なmatplotlibメソッドがあるかどうか疑問に思っていましたafter定義されました。残念ながら、matplotlib APIを読むことは役に立ちませんでした。

26
Denis Sergeev

既存の軸の投影を変更することはできません。その理由は次のとおりです。しかし、根本的な問題の解決策は、matplotlibのドキュメントで説明されているplt.subplots()subplot_kw引数を使用することです here 。たとえば、すべてのサブプロットにcartopy.crs.PlateCarreeプロジェクションを持たせたい場合

import matplotlib.pyplot as plt
import cartopy.crs as ccrs

# Create a grid of plots
fig, (ax1, ax2) = plt.subplots(ncols=2, subplot_kw={'projection': ccrs.PlateCarree()})

実際の質問に関しては、軸セットを作成するときに投影を指定すると、取得する軸クラスが決まります。これは、投影タイプごとに異なります。例えば

import matplotlib.pyplot as plt
import cartopy.crs as ccrs

ax1 = plt.subplot(311)
ax2 = plt.subplot(312, projection='polar')
ax3 = plt.subplot(313, projection=ccrs.PlateCarree())

print(type(ax1))
print(type(ax2))
print(type(ax3))

このコードは次を印刷します

<class 'matplotlib.axes._subplots.AxesSubplot'>
<class 'matplotlib.axes._subplots.PolarAxesSubplot'>
<class 'cartopy.mpl.geoaxes.GeoAxesSubplot'>

各軸が実際に異なるクラスのインスタンスであることに注意してください。

32
ajdawson

この質問への答えに従って:

Pythonでは、クラスインスタンスのメソッドを継承してオーバーライドし、この新しいバージョンを古いバージョンと同じ名前に割り当てるにはどうすればよいですか?

私はそれを作成した後にaの投影を変更するハックを見つけましたが、これは少なくとも以下の簡単な例ではうまくいくようですが、この解決策が最良の方法であるかどうかはわかりません

from matplotlib.axes import Axes
from matplotlib.projections import register_projection

class CustomAxe(Axes):
    name = 'customaxe'

    def plotko(self, x):
        self.plot(x, 'ko')
        self.set_title('CustomAxe')

register_projection(CustomAxe)


if __name__ == '__main__':
    import matplotlib.pyplot as plt

    fig = plt.figure()

    ## use this syntax to create a customaxe directly
    # ax = fig.add_subplot(111, projection="customaxe")

    ## change the projection after creation
    ax = plt.gca()
    ax.__class__ = CustomAxe

    ax.plotko(range(10))    
    plt.show()
0
user2660966