使用 Cartopy 繪制精美的地圖

Hello 大家好,我是小駿。
從事氣象繪圖相關(guān)工作的朋友應(yīng)該知道 Cartopy 這個 Python 庫,它可以用來繪制各種投影的地圖。

它默認(rèn)采用 Natural Earth 提供的豐富的底圖文件,其中包含了地球上的海洋、陸地、河流、湖泊、海岸線、國界等等,繪制地圖時所需要的各種特征文件。


Cartopy 繪圖部份依賴 Matplotlib 庫,因此配合 Matplotlib 的各種繪圖方法,基本上可以畫出任何樣式的圖。當(dāng)然,前提是要好好查文檔,理解 API,并且花時間去折騰。??

那么這篇專欄就簡單介紹一下如何用 Cartopy 繪制我們想要的地圖。 按照我們的慣例,我也錄制了視頻,大家可以點開來對照文章看。
我們可能見過很多種地圖,它們顯示的形狀好像不太一樣,這是因為地圖有「投影」的區(qū)別。Cartopy 中常用的投影有圓柱投影、蘭伯特投影、羅賓遜投影、墨卡托投影、正射投影等等,我工作中常用的也就圓柱投影和蘭伯特投影這兩種。
下圖就是一張圓柱投影的圖,橫坐標(biāo)是經(jīng)度,縱坐標(biāo)是緯度。這種投影好比把地球儀上的那層紙揭了下來,強(qiáng)行攤平成了一個長方形。所以越靠近 0 度緯線,也就是赤道的部分,越接近真實的大?。辉娇拷鼉蓸O,相較于真實形狀,拉伸程度越高。

下圖是一張?zhí)m伯特投影的圖,這種投影我覺得看起來更舒服一點。感覺上是只把局部的半球面做了拉平處理,所以看起來形變的程度不是很大。

運行下面的代碼,就可以畫出一幅圓柱投影的圖。
簡單讀過代碼可以知道,我們可以給指定的 feature 涂上任意顏色。比如把海洋掩蓋掉涂成白色,就像代碼中把參數(shù) facecolor 設(shè)置成 white 就可以了。

那我如果想突出顯示某個國家該怎么做?這就需要深入研究一下畫圖用到的 shapefile 文件的構(gòu)成,以及代碼調(diào)用它的方式。這里大家可以看一下這位大佬的博客,詳細(xì)總結(jié)了 shapefile 是由各種 shape 和 attribute 來表示地圖中的點、線、面等要素。
當(dāng)然我們也可以直接問一下 ChatGPT,看看強(qiáng)大的人工智能能否言簡意賅的解釋清楚。

綜合查閱資料后,我們知道可以這樣讀取 shapefile 中的內(nèi)容:
遍歷 shapefile 時,每個元素都標(biāo)注了屬性,里面就有我們想要的國家名稱和所屬大洲名稱。我們可以通過比對屬性字典中的 NAME_ZH 字段(國家名稱簡體中文)來篩選國家,或?CONTINENT 字段(大洲英文)來篩選大洲。這里要注意,Natural Earth 提供的文件有三個分辨率,我們選擇 1:10m 的分辨率,才會完整的包含全部國家和地區(qū)。
下圖就是把澳大利亞標(biāo)紅后的效果:

我們從 ERA 的官網(wǎng)上隨便下載一個氣溫數(shù)據(jù),可以繪制出這樣的填色圖。

使用相同的方法,我們可以將澳大利亞之外的部分涂成白色:
出圖圖下:

但是在氣象繪圖工作中,不僅需要靈活地畫出指定區(qū)域,有時還需要對指定區(qū)域的數(shù)據(jù)做計算評估。我們使用上面的方法實質(zhì)上僅僅是在處理圖層,數(shù)據(jù)圖層只是被遮起來了而已,并沒有做實際的更改。
這個數(shù)據(jù)是全球的內(nèi)容,如果我們想只繪制澳大利亞區(qū)域的數(shù)據(jù),該怎么做呢?
這里就需要根據(jù) shapefile 文件制作掩膜數(shù)據(jù),然后將氣溫數(shù)據(jù)與掩膜數(shù)據(jù)不重合的部分抹去。這里使用前面博客作者開發(fā)的?frykit 這個庫,來完成掩膜數(shù)據(jù)的制作。
為了能更方便地驗證我們的數(shù)據(jù)確實被修改了,可以把數(shù)據(jù)導(dǎo)出成 NC 數(shù)據(jù),使用 Panoply 這個軟件來直觀地看到數(shù)據(jù)形狀。

我們用這個掩膜數(shù)據(jù),使用 xarray.where() 方法,將上面填色圖的數(shù)據(jù)掩蓋掉,就可以達(dá)到只繪制澳大利亞區(qū)域的目的了。
可以再用 Panoply 查看一下處理后的數(shù)據(jù):

使用這個數(shù)據(jù),無需對圖層做處理,直接繪制填色圖,下圖的效果就是我們想要的樣子。

現(xiàn)在就可以對數(shù)據(jù)做統(tǒng)計計算,比如最大值、最小值、平均值等等。

總結(jié)
這篇文章想介紹的內(nèi)容差不多就是這些了,但是說的都比較淺。代碼中用到的許多庫其實需要對照官方文檔或其他資料去練習(xí),比如讀取網(wǎng)格數(shù)據(jù)時用到的 Xarray 庫的使用;網(wǎng)格數(shù)據(jù)的 GRIB、NC 等各種數(shù)據(jù)格式規(guī)范、讀取方式;Matplotlib 中的填色圖(pcolormesh)、等值面圖(contourf)、散點圖(scatter)、色標(biāo)的設(shè)置(cmap、norm);以及處理數(shù)據(jù)時用到的 Pandas、Numpy、Scipy 庫的使用;更換正確的中國底圖;以及各種氣象數(shù)據(jù)統(tǒng)計相關(guān)的理論知識等等。說好聽點就是這里的知識博大精深,說的粗糙一點就是坑非常多。
這些知識我也是一知半解,邊用邊查,所以沒有講的太深。
如果你覺得這篇文章有幫到你,可以點個贊,如果期待后續(xù)內(nèi)容,可以點個關(guān)注。
那么我們下期再見,拜拜。??

參考資料
Natural Earth 官方網(wǎng)站:https://www.naturalearthdata.com/
zhajiman 大佬博客:https://zhajiman.github.io/post/cartopy_shapefile/
cnmaps 官方文檔:https://cnmaps-doc.readthedocs.io/zh_CN/latest/index.html
Matplotlib 官方文檔:https://matplotlib.org/stable/index.html
Xarray 官方文檔:https://docs.xarray.dev/en/stable/index.html
Cartopy 官方文檔:https://scitools.org.uk/cartopy/docs/latest/
Panoply 下載頁面:https://www.giss.nasa.gov/tools/panoply/download/
ERA 數(shù)據(jù)下載:https://cds.climate.copernicus.eu/#!/search?text=ERA5&type=dataset
frykit 庫 GitHub 倉庫:https://github.com/ZhaJiMan/frykit