地図をかく (2) 正距円筒図法の地図を組み立てる

[その (1)] につづいて、cartopy によって地図をかく。 ここでは、正距円筒図法 (plate carree) の世界地図をつくるばあいにしぼって、 プログラムの組み立てを見ていく。

このページのプログラム例は、つぎのウェブサイトで提供された例をまねしたところがある。


(62a) 投影の指定

matplotlib と cartopy を利用する。

matplotlib で図をかくための手順にはいくつかの方法があるが、 山下さんの例文にあわせて、 figure (「fig」) と axes (「ax」) をわける方法をとり、 さらに、ひとつの figure の中に複数の subplot をもつ形を標準とし、 ひとつだけの図をかくときも add_subplot を 「fig を 1×1に分割してそのうち1番めの場所に作図する」ような形で 呼ぶ手順をとることにする。

例文では、プロット領域 (figure) として「fig」を確保し、 その第1の (このばあいには唯一の) subplot で、PlateCarree という地図投影をつかうこと、 その中心経線は 東経150度 (この数値は山下さんの例文とちがい、増田が設定した) とすることを指定している。

最後に plt.show() で画面に図を表示するが、 この例文のままでは、表示されるのは長方形の枠だけである。

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

# プロット領域の作成
fig = plt.figure()

# cartopy 呼び出し
ax = fig.add_subplot(1,1,1,projection=ccrs.PlateCarree(central_longitude=150))

# 画面に表示
plt.show()

これを [62a_world0.py] とする。


(62b) 海岸線をひく

「cartopy 呼び出し」の部分と「画面に表示」の部分のあいだに、つぎのコードを入れる。

# 海岸線を描く
ax.coastlines()

これを入れたものを [62b_world1.py] とする。


(62c) 経線・緯線をひく

つぎのように ax.gridlines() をつかって、経線・緯線をひくことができる。 線をひく経度・緯度の値をきめるために、matplotlib.ticker の FixedLocator という関数をつかう。

# 経度・緯度線をひく
gl = ax.gridlines(crs=ccrs.PlateCarree())
gl.xlocator = mticker.FixedLocator(np.arange(-180, 180, 30)) # 経度線
gl.ylocator = mticker.FixedLocator(np.arange( -90,  90, 30)) # 緯度線

その準備として、つぎの手続きが必要になる。

import matplotlib.ticker as mticker

これを組みこんだプログラムを [62c_world2.py] とする。

なお、ax.gridlines で、線の種類を指定することができる。 たとえば、つぎのように変えると、赤の細めの破線になる。 (「\」 (バックスラッシュ、端末のフォントによっては円マーク) は、Pythonの文法上の約束で、 プログラムの行の継続をしめす。)

gl = ax.gridlines(crs=ccrs.PlateCarree(),\
    linewidth=0.5, linestyle='--', color='r', alpha=0.8)

(62d) 経線・緯線の経度・緯度のラベルをつける

ax.gridlines で「draw_labels=True」というオプションをつかうと、 緯線・経線の緯度・経度の数値をしめすラベルが追加される。

gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True)

ただし、この例の結果はあまりうまくない。 ラベルの文字が省略されてしまっていることがある。文字がかさなるのをさけるためらしい。 ax.gridlines でかかれるラベルの文字の大きさを制御する方法がよくわからないが、 plt.figure の呼び出しをつぎのように変更し、図をかく紙にあたるものを大きくすれば、 (かさなる心配がなくなるので) 省略されなくなる。

fig = plt.figure(figsize=(8, 6))

(図の右端の経度のラベルが省略されることはあいかわらずである。 右端が地球上で左端と同じ場所だからだと思うが、対策はわからない。)

また、図の上側と下側のラベルは一方でよいことが多い。 つぎのようにすれば、上側のラベルを省略できる。

gl.top_labels = False

右側のレベルは表示されていないが、 本来は表示されるはずのものである (中心経線を指定しないときは表示される)。 つぎのようにすれば、右側のラベルを省略することを指示できる。

gl.right_labels = False

以上の変更をしたプログラムが、[62d_world3.py] である。


(62e) 領域を限定した地図: 東アジア

[その (1)] でかいた「東アジア」の地図のように 経度・緯度で領域を限定した地図をかくことができる。

「cartopy 呼び出し」のすぐあとで、つぎのように ax.set_extent で 経度の下限・上限、緯度の下限・上限をまとめたリストで指定する。 符号は、東経・北緯が正、西経・南緯が負である。 (set_extent での 投影方法の指定は、位置座標の解釈のためのものなので、 作図する地図の投影図法が正距円筒図法でなくても PlateCarree を指定する。)

# 経度・緯度範囲を限定する
lonmin =  110
lonmax =  170
latmin =   10
latmax =   60
ax.set_extent([lonmin, lonmax, latmin, latmax], ccrs.PlateCarree())

経度線・緯度線の間隔を図の範囲にあわせて設定しなおす。ここでは 10度にしてみた。 それとともに、軸の目盛りに緯度・経度の数値ラベルをつける方法を変える。 目盛りをつける ax.set_xticks, ax.set_yticks にともなう ax.set_xticklabels, ax.set_yticklabels で指定するようにした。 【ただし、この方法は正距円筒図法以外の地図投影ではうまくいかないかもしれない。】 (62d) のように ax_gridlines による格子線にあわせてかかせる方法だと、 図の領域の端にあたる緯線・経線にラベルをつけてくれなかったからである。

# 緯度・経度目盛りをかく (正距円筒図法専用)
dlon    =   10
dlat    =   10
lolaeps =    1
xticks = np.arange(lonmin, lonmax+lolaeps,  dlon)
yticks = np.arange(latmin, latmax+lolaeps,  dlat)
ax.set_xticks(xticks, crs=ccrs.PlateCarree())
ax.set_yticks(yticks, crs=ccrs.PlateCarree())
ax.set_xticklabels(xticks, fontsize=12)
ax.set_yticklabels(yticks, fontsize=12)
lon_formatter = LongitudeFormatter()
lat_formatter = LatitudeFormatter()
ax.xaxis.set_major_formatter(lon_formatter)
ax.yaxis.set_major_formatter(lat_formatter)

海岸線のデータが世界地図用のものでは あらいので、もうすこしこまかいものにしてみる。 「50m」の m は (メートルではなく) million で、縮尺が 5千万分の1の地図に適切なくわしさ、という意味だそうだ。

# 海岸線を描く
ax.coastlines(resolution='50m')

以上の変更をしたプログラムが [62e_eastasia.py] である。


(62f) 領域を限定した地図: 日本の中央部

さらに緯度・経度範囲を限定してみる。 海岸線データも「10m」(縮尺 1千万分の1の地図用のくわしさ) にする。

# 経度・緯度範囲を限定する
lonmin =  132
lonmax =  142
latmin =   30
latmax =   40
# 海岸線を描く
ax.coastlines(resolution='10m')
# 緯度・経度目盛りをかく (正距円筒図法専用)
dlon    =    2
dlat    =    2
lolaeps =    0.5

以上の変更をしたプログラムが [62f_cjapan.py] である。


(62g) 領域を限定した地図: 関東・中部地方

さらに緯度・経度範囲を限定してみる。

# 経度・緯度範囲を限定する
lonmin =  136
lonmax =  141.5
latmin =   34
latmax =   38.5
# 緯度・経度目盛りをかく (正距円筒図法専用)
dlon    =    1.0
dlat    =    0.5
lolaeps =    0.1

以上の変更をしたプログラムが [62g_kanto_chubu.py] である。


(62h) 都道府県境をくわえる

都道府県の境界を入れるためには、境界線の緯度経度情報をもつデータが必要である。 Cartopy で利用している海岸線データを提供する 「Natural Earth」のサイトには世界各国の主要行政界のデータもある。 Cartopy でそれを実行時にとりこんで作図するプログラム例があったのだが、 授業でやってみると動作が不確実だった。 そこで、増田があらかじめ Natural Earth の主要行政界のデータ (「10m」のくわしさのもの) をダウンロードし、 日本の部分だけを抽出したものを用意して、 niigata では /home/masudako/mapdata/ne/ に置き、 プログラムではそこにあるデータを読むことにした。

つぎの [62h_kanto_chubu.py] は、(62g) のプログラムに、都道府県境を追加したものである。

しかけを知りたい人や、niigata 以外のマシンでつかいたい人は、 [日本の都道府県境をかく / 中国の「省」の境をかく] のページを見てほしい。


(2022-06-25, 2023-06-13) 2024-06-18
増田 耕一 (MASUDA Kooiti)
増田の [B, F, G 合同セミナーのページ] [立正大学用教材目次] [計算機を利用した気象分野の実習教材目次] [教材目次]