前言
嗨,你好,我是來自點點GIS的南南
我與Cartopy的認識起源于“氣象水文科研貓”的這個推文,那時候的我覺得,用代碼畫地圖好酷,arcgis就感覺low爆了。但是一直沒有時間學習。前段時間放暑假,磕磕絆絆裝完包以后就不想動彈了,折騰環(huán)境折騰的我頭皮發(fā)麻。gdal和cartopy真的是我學python以來裝的最麻煩的包。
很多時候我想學習,卻感覺無從下手,大佬們的博文一大堆,我看了以后只有一句“臥槽,牛逼”,然后沒然后了。前幾天某人欺負我,把我整抑郁了,大晚上睡不著覺,就想著填個坑,雖然我技術(shù)菜,不能“炫技”,但寫個入門教程難不倒我吧。然后就有了這篇文章。
這篇文章參考了諸多大佬的博文,如氣象學家,云臺書使,氣象學人,好奇心Log,等等公眾號大佬。我作為初學者,寫的文肯定錯誤不少,歡迎大家給我留言指正,要是有老板叫我去打工就更好了,嘿嘿嘿
Emil:2531788189@qq.com
Cartopy介紹
Cartopy 是一個開源免費的第三方 Python 擴展包,由英國氣象辦公室的科學家們開發(fā),支持 Python 2.7 和 Python 3,致力于使用最簡單直觀的方式生成地圖,并提供對 matplotlib 友好的協(xié)作接口。
在常用的python繪圖庫中,basemap,geopandas,pyecharts等,其中basemap已經(jīng)停止維護了,在前文中我已經(jīng)講到過,pyecharts是用于數(shù)據(jù)可視化等專業(yè)圖表的繪制,之前我的文章也介紹過,pyecharts在地學可視化中功能實在過于簡陋;geopandas是基于pandas的,一般用于商業(yè)數(shù)據(jù)分析,所以我更推薦大家學習Cartopy,雖然Cartopy氣象專業(yè)用得很多哈哈哈
Cartopy安裝
https://mp.weixin.qq.com/s/GW6odDBGLPVRZTKx0YZLVg
Cartopy繪圖入門
在Cartopy的使用過程中,我們常常需要搭配其他庫一起使用,常用的有如Matplotlib ,numpy,pandas,gma等
Cartopy投影
Cartopy 是利用 Matplotlib 來畫圖的,因此首先要導入 pyplot
模塊。在 Cartopy 中,每種投影都是一個類,被存放在 cartopy.crs
模塊中,crs 即坐標參考系統(tǒng)(Coordinate Reference Systems)之意。所以接著要導入這個模塊。
投影用法示例:
proj = ccrs.PlateCarree() #proj = ccrs.投影()
這里簡單說明一下常用的三種投影,Cartopy 大概有三四十種投影,如國想詳細了解可以參考下面的文章
https://scitools.org.uk/cartopy/docs/v0.15/crs/projections.html
默認投影 | PlateCarree |
---|---|
墨卡托投影 | Mercator |
蘭勃脫投影 | Lambert |
默認投影適合單獨省份或者地級市的繪制,蘭勃脫投影適合中緯度大范圍繪制,比如繪制全中國大公雞、東亞形勢、西北太平洋等;墨卡托投影適合低緯度赤道附近的繪制,一般研究臺風、緯向環(huán)流等
繪制地圖示例
將 cartopy 集成到 matplotlib 的主要類是 GeoAxes,它是普通 matplotlib Axes 的子類。GeoAxes 類為特定于繪制地圖的軸添加了額外的功能。創(chuàng)建一個 GeoAxes
對象的辦法是,在創(chuàng)建 axes(或 subplot)時,通過參數(shù) projection
指定一個 ccrs
中的投影。這里便利用這一方法生成了一個等距圓柱投影下的 ax。
最后調(diào)用 ax 的方法 coastlines
畫出海岸線,默認以本初子午線為中心,比例尺為 1:110m(m 表示 million)。
因此用 Cartopy 畫地圖的基本流程并不復雜:
-
創(chuàng)建畫布。
-
通過指定
projection
參數(shù),創(chuàng)建GeoAxes
對象。 -
調(diào)用
GeoAxes
的方法畫圖。 -
GeoAxes
用法擴展(部分常用)-
set_global
:讓地圖的顯示范圍擴展至投影的最大范圍。例如,對PlateCarree
投影的 ax 使用后,地圖會變成全球的。 -
set_extent
:給出元組(x0, x1, y0, y1)
以限制地圖的顯示范圍。 -
set_xticks
:設(shè)置 x 軸的刻度。 -
set_yticks
:設(shè)置 y 軸的刻度。 -
gridlines
:給地圖添加網(wǎng)格線。 -
coastlines
:在地圖上繪制海岸線。 -
stock_img
:給地圖添加低分辨率的地形圖背景。 -
add_feature
:給地圖添加特征(例如陸地或海洋的填充、河流等)。
-
import matplotlib.pyplot as plt###引入庫包
import cartopy.crs as ccrs
proj = ccrs.PlateCarree()
fig = plt.figure(figsize=(4, 4), dpi=200) # 創(chuàng)建畫布
ax = plt.axes(projection=ccrs.PlateCarree())# 創(chuàng)建子圖
ax.coastlines()# 調(diào)用ax的方法畫海岸線
'''
fig語法:
figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)
num:圖像編號或名稱,數(shù)字為編號 ,字符串為名稱
figsize:指定figure的寬和高,單位為英寸;
dpi參數(shù)指定繪圖對象的分辨率,即每英寸多少個像素,缺省值為80 1英寸等于2.5cm,A4紙是 21*30cm的紙張
facecolor:背景顏色
edgecolor:邊框顏色
frameon:是否顯示邊框
'''
如需修改中央經(jīng)線,可以在創(chuàng)建子圖的時候指定一些參數(shù)
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))#全球圖像的中央位于太平洋的 180 度經(jīng)線處
也可以在繪制線條的時候指定線寬
ax.coastlines(lw=0.3)#線條寬度0.3
在地圖上添加特征
上面的地圖是一個十分粗糙的地圖,僅有海岸線,嘗試一下添加更多地理信息
添加預定義要素
首先需要導入一個cartopy.feature
常量,為了簡化一些非常常見的情況,如大陸海洋國界等cartopy
都已經(jīng)進行了預定義,但需要注意的是直接導入的中國國界線并不是標準的,在使用時需要注意
這些信息帶有三種分辨率,分別為110m,50m和10m。
import matplotlib.pyplot as plt###引入庫包
import cartopy.crs as ccrs
import cartopy.feature as cfeature#預定義常量
proj = ccrs.PlateCarree()
fig = plt.figure(figsize=(4, 4), dpi=200) # 創(chuàng)建畫布
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))#全球圖像的中央位于太平洋的 180 度經(jīng)線處
ax.add_feature(cfeature.LAND)#添加陸地
ax.add_feature(cfeature.COASTLINE,lw = 0.3)#添加海岸線
ax.add_feature(cfeature.RIVERS,lw = 0.25)#添加河流
#ax.add_feature(cfeat.RIVERS.with_scale('50m'),lw = 0.25) # 加載分辨率為50的河流
ax.add_feature(cfeature.LAKES)#添加湖泊
ax.add_feature(cfeature.BORDERS, linestyle = '-',lw = 0.25)#不推薦,因為該默認參數(shù)會使得我國部分領(lǐng)土丟失
ax.add_feature(cfeature.OCEAN)#添加海洋
ax.coastlines(lw=0.3)
在cartopy中,所有的線條都可以改變他的粗細。只用改變其參數(shù)lw = *
即可
ax.add_feature(cfeature.RIVERS,lw = 2)#改變河流粗細
同樣的,所有的線,面也可以改變它的顏色
ax.add_feature(cfeature.LAKES,color='r')#指定湖泊顏色為紅色
添加經(jīng)緯度標簽
這里還是要用到前文說過的GeoAxes
用法
-
set_xticks
:設(shè)置 x 軸的刻度。 -
set_yticks
:設(shè)置 y 軸的刻度。
例:x軸為(-180,-120,-60,0,60,120,180),y軸為(-90,-60, -30, 0, 30, 60,90)
x_extent = [ 0, 60, 120, 180, 240, 300, 360]#經(jīng)緯度范圍,#直接使用(-180,-120,-60,0,60,120,180)會異常,需要寫成(0, 60, 120, 180, 240, 300, 360)的形式
y_extent = [ -90,-60, -30, 0, 30, 60,90]
fig = plt.figure(figsize=(4, 4), dpi=200)
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
ax.add_feature(cfeature.LAND)#添加陸地
ax.add_feature(cfeature.COASTLINE,lw = 0.3)#添加海岸線
ax.add_feature(cfeature.RIVERS,lw = 0.25)#添加河流
ax.add_feature(cfeature.LAKES)#指定湖泊顏色為紅色#添加湖泊
#ax.add_feature(cfeature.BORDERS, linestyle = '-',lw = 0.25)#不推薦,因為該默認參數(shù)會使得我國部分領(lǐng)土丟失
ax.add_feature(cfeature.OCEAN)#添加海洋
ax.set_xticks(x_extent, crs=ccrs.PlateCarree())#添加經(jīng)緯度
ax.set_yticks(y_extent, crs=ccrs.PlateCarree())
將經(jīng)緯度標簽轉(zhuǎn)換為具有單位的形式
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter #導入Cartopy專門提供的經(jīng)緯度的Formatter
x_extent = [ 0, 60, 120, 180, 240, 300, 360]#經(jīng)緯度范圍,#直接使用(-180,-120,-60,0,60,120,180)會異常,需要寫成(0, 60, 120, 180, 240, 300, 360)的形式
y_extent = [ -90,-60, -30, 0, 30, 60,90]
fig = plt.figure(figsize=(4, 4), dpi=200)
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
ax.add_feature(cfeature.LAND)#添加陸地
ax.add_feature(cfeature.COASTLINE,lw = 0.3)#添加海岸線
ax.add_feature(cfeature.RIVERS,lw = 0.25)#添加河流
ax.add_feature(cfeature.LAKES)#指定湖泊顏色為紅色#添加湖泊
#ax.add_feature(cfeature.BORDERS, linestyle = '-',lw = 0.25)#不推薦,因為該默認參數(shù)會使得我國部分領(lǐng)土丟失
ax.add_feature(cfeature.OCEAN)#添加海洋
ax.set_xticks(x_extent, crs=ccrs.PlateCarree())#添加經(jīng)緯度
ax.set_yticks(y_extent, crs=ccrs.PlateCarree())
# 利用Formatter格式化刻度標簽
lon_formatter = LongitudeFormatter(zero_direction_label=False)
lat_formatter = LatitudeFormatter()
ax.xaxis.set_major_formatter(lon_formatter)
ax.yaxis.set_major_formatter(lat_formatter)
經(jīng)緯網(wǎng)
在前文中GeoAxes
用法提到過添加經(jīng)緯網(wǎng)的函數(shù)gridlines
,只用在上述代碼末尾中添加ax.gridlines()
,即
ax.gridlines()#添加網(wǎng)格
這實在是太丑了,給它換個線樣式
ax.gridlines(linestyle='--')#添加網(wǎng)格,線樣式為'--'
配上網(wǎng)格總感覺刻度朝外怪怪的
ax.tick_params(color = 'blue',direction='in')#更改刻度指向為朝內(nèi),顏色設(shè)置為藍色
更多GeoAxes
用法可以參考以下文章
https://scitools.org.uk/cartopy/docs/v0.14/matplotlib/feature_interface.html
局部地圖
很多時候我們繪圖不會用到世界地圖,所以可以嘗試更改你的范圍。cartopy提供更改的方式是通過定義經(jīng)緯度范圍來進行更改的。在上述代碼末尾添加下方樣例代碼試試
set_extent
:給出元組 (x0, x1, y0, y1)
以限制地圖的顯示范圍。
ax.set_extent([0,180,0,35],crs = ccrs.PlateCarree()) #選取經(jīng)度為0°E-180°E,緯度為0°N-90°N的區(qū)域
添加標題
ax.set_title('Cartopy') #添加標題Cartopy
Cartopy繪圖進階
在前文中提到過,Cartopy的中國地圖邊界是有問題的,那么在日常使用中,我們該如何避免這些問題呢?
Cartopy中國地圖繪制方法
方法一
用 Cartopy 的 shapereader 讀取后即可繪制。 Cartopy 的 shapereader用法示例可參考以下文章
https://scitools.org.uk/cartopy/docs/v0.15/tutorials/using_the_shapereader.html
關(guān)于正確的行政邊界獲取可以參考以下博文
https://mp.weixin.qq.com/s/aUCjTRrV6Cz-k7mtXOEiGw
使用cartopy讀取shapefile繪制共有兩種方法,分別是add_feature和add_geometries,但無論你使用哪種方法,你都需要先讀取文件才能夠添加。Cartopy提供了一個基于pyshp的接口以實現(xiàn)對地理文件的簡單讀取和操作:
首先導入相關(guān)包
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cfeat
import cartopy.io.shapereader as shapereader
你找他總得給他來一個地址吧
shp_path = "D:/data2/china/china/province_9south.shp"#切記路徑一定要英文,血的教訓?。?!
繪圖三部曲,畫布,投影,子圖
fig = plt.figure(figsize=(6,6)) #創(chuàng)建畫布
proj = ccrs.PlateCarree()#創(chuàng)建投影,選擇cartopy的默認投影
ax = fig.subplots(1, 1, subplot_kw={'projection': proj}) #子圖
extent = [70,140,2,60]#限定繪圖范圍
add_feature加載自定義地圖
china_map = cfeat.ShapelyFeature(shapereader.Reader(china_map).geometries(), proj, edgecolor='k', facecolor='none')
ax.add_feature(china_map, linewidth=1)
ax.set_extent(extent, crs=proj)
add_geometries加載自定義地圖
ax.add_geometries(shapereader.Reader(china_map).geometries(), crs=proj, facecolor='none',edgecolor='k',linewidth=1)
ax.set_extent(extent, crs=proj)
完整代碼如下
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cfeat
import cartopy.io.shapereader as shapereader
shp_path = "D:/data2/china/china/province_9south.shp"#切記路徑一定要英文,血的教訓!?。?/span>
fig = plt.figure(figsize=(6,6)) #創(chuàng)建畫布
proj = ccrs.PlateCarree()#創(chuàng)建投影,選擇cartopy的默認投影
ax = fig.subplots(1, 1, subplot_kw={'projection': proj}) #子圖
extent = [70,140,2,60]#限定繪圖范圍
china_map = cfeat.ShapelyFeature(shapereader.Reader(shp_path).geometries(), proj, edgecolor='k', facecolor='none')
ax.add_feature(china_map, linewidth=1)#添加讀取的數(shù)據(jù),設(shè)置線寬
ax.set_extent(extent, crs=proj)
#ax.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj, #facecolor='none',edgecolor='k',linewidth=1)
#ax.set_extent(extent, crs=proj)
方法二
使用GMT 中文社區(qū)上提供的省界的經(jīng)緯度數(shù)據(jù)進行繪圖。GMT 中文社區(qū)為用戶提供了一套名為CN-border的基本準確的數(shù)字化中國國界,、省界數(shù)據(jù)。在此向 GMT 中文社區(qū)的維護和貢獻者表示感謝!
但需要注意的是,即便正確繪制了國界、省界,所繪地圖如果要在境內(nèi)公開展示,依然需要審圖。個人沒有提交審圖申請的資格,需要付費,委托給有資質(zhì)的企事業(yè)單位代為提交審圖申請。下為GMT 中文社區(qū)網(wǎng)址,大家可自行下載
https://docs.gmt-china.org/latest/dataset-CN/CN-border/
CN-border 數(shù)據(jù)提供了三個數(shù)據(jù)文件:
-
CN-border-La.gmt
:中國國界、省界、十段線以及南海諸島數(shù)據(jù) -
CN-border-L1.gmt
:中國國界、十段線以及南海諸島數(shù)據(jù),不含省界數(shù)據(jù) -
ten-dash-line.gmt
:僅十段線數(shù)據(jù)
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
#加載邊界數(shù)據(jù),CN-border-La.dat下載
#https://github.com/gmt-china/china-geospatial-data/releases
with open('C:/Users/啊啊啊啊/Desktop/china-geospatial-data-GB2312/CN-border-La.gmt') as src:
context = src.read()
blocks = [cnt for cnt in context.split('>') if len(cnt) > 0]
borders = [np.fromstring(block, dtype=float, sep=' ') for block in blocks]
# 畫布
fig = plt.figure(figsize=[10, 8])
# 設(shè)置投影并繪制主圖形
ax = plt.axes(projection=ccrs.LambertConformal(central_latitude=90,
central_longitude=105))
# 繪制線條
for line in borders:
ax.plot(line[0::2], line[1::2], '-', lw=1, color='k',
transform=ccrs.Geodetic())
# 繪制邊界線
for line in borders:
sub_ax.plot(line[0::2], line[1::2], '-', lw=1, color='k',
transform=ccrs.Geodetic())
# 設(shè)置圖形范圍
sub_ax.set_extent([105, 125, 0, 25])
# 顯示圖形
plt.show()
方法三
cnmaps繪圖,cnmaps是Cartopy的一個擴展包,內(nèi)置了中國地圖數(shù)據(jù)源,該數(shù)據(jù)源自高德地圖API,大家可以自行去該項目進行學習
https://github.com/Clarmy/cnmaps
重點區(qū)域突出顯示
該示例是在前文方法一的基礎(chǔ)上進行繪制
Cartopy 默認對所有地物使用相同的外觀,如果需要突出顯示某些地物,就必須進行篩選。這里從province_9south.shp這份全國省級行政區(qū)劃數(shù)據(jù)中選中山西(通過屬性表SHENG_ID字段),然后使用 ax.add_geometries() 方法將它們加入到原有地圖元素中。
for state, geos in zip(shapereader.Reader(shp_path).records(), shapereader.Reader(shp_path).geometries()) :
if state.attributes['SHENG_ID'] in [14 ]:#如果'14'在'SHENG_ID'這個字段中
ax.add_geometries([geos], crs=proj,facecolor='None', edgecolor='blue') # 重點區(qū)域上色
關(guān)于屬性表,你可以通過gdal來打印出該shpfile文件所具有的屬性表,也可以通過arcgis,qgis等GIS軟件打開查詢
僅繪制山西省
注意在前文中我加粗的那個詞“加入”這意味著上文中重點區(qū)域突出顯示的山西省圖層是經(jīng)過篩選而添加到地圖中的,而不是對山西省這個范圍進行符號化,如果我們要只顯示山西省的話,就將上述代碼中顯示全國范圍的代碼注釋掉即可,參見下方示例代碼
fig = plt.figure(figsize=(6,6))
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
#ax.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj,facecolor='none',edgecolor='k',linewidth=1)
ax.set_extent(extent, crs=proj)
for state, geos in zip(shapereader.Reader(shp_path).records(), shapereader.Reader(shp_path).geometries()) :
if state.attributes['SHENG_ID'] in [14]:
ax.add_geometries([geos], crs=proj,facecolor='None', edgecolor='red') # 重點區(qū)域上色
添加南海小地圖
在之前的的學習中我們知道,cartopy繪制的地圖稱為子圖,在繪制中國地圖時候,有時候由于地圖大小的限制,我們無法展示部分地區(qū)如南海,常規(guī)的方法是繪制兩幅地圖,比如一張為全國地圖,一張為局部地圖,也就是常說的南海小地圖。
常見的subplot和subplot2grid函數(shù)一般來說繪制的地圖大小是一樣的,不容易展示比例大小,所以我們選擇add_axes()命令來繪制兩個大小不一樣的子圖。需要注意的是在繪制時我們需要定義兩個extent參數(shù),即分別為總的地圖和南海小地圖分別定義畫布大小繪圖范圍
extent = [105, 133, 15, 45]#限定繪圖范圍
fig = plt.figure(figsize=(6,8)) #注意畫布大小
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
ax.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj,facecolor='none',edgecolor='k',linewidth=1)
ax.set_extent(extent, crs=proj)
left, bottom, width, height = 0.67, 0.16, 0.23, 0.27#南海小地圖大小
ax2 = fig.add_axes([left, bottom, width, height], projection=proj)
ax2.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj, facecolor='none',edgecolor='k',linewidth=1)
ax2.set_extent([105, 125, 0, 25])#注意南海小地圖的范圍
添加地形圖背景
一個簡單的嘗試
在看完了上述內(nèi)容后還是覺得有些不足,讓我們結(jié)合來Cartopy繪圖入門中所講述的內(nèi)容來給他添加一個背景吧
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cfeature
import cartopy.io.shapereader as shapereader
shp_path = "D:/data2/china/china/province_9south.shp"#切記路徑一定要英文,血的教訓?。?!
fig = plt.figure(figsize=(6,8)) #注意畫布大小
proj = ccrs.PlateCarree()#創(chuàng)建投影,選擇cartopy的默認投影
ax = fig.subplots(1, 1, subplot_kw={'projection': proj}) #子圖
extent = [105, 133, 15, 45]#限定繪圖范圍
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
ax.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj,facecolor='none',edgecolor='k',linewidth=1)
ax.set_extent(extent, crs=proj)
#添加其他要素
ax.add_feature(cfeature.OCEAN.with_scale('50m'))
ax.add_feature(cfeature.LAND.with_scale('50m'))
ax.add_feature(cfeature.RIVERS.with_scale('50m'))
ax.add_feature(cfeature.LAKES.with_scale('50m'))
left, bottom, width, height = 0.67, 0.16, 0.23, 0.27#南海小地圖大小
ax2 = fig.add_axes([left, bottom, width, height], projection=proj)
ax2.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj, facecolor='none',edgecolor='k',linewidth=1)
ax2.set_extent([105, 125, 0, 25])#注意南海小地圖的范圍
這時候我們會疑惑,為什么南海小地圖還是這樣。在上文中提到過,南海小地圖是另一幅地圖,他與原來的中國地圖你可以理解為是兩幅地圖。所以也需要在南海小地圖中添加要素,也就是ax2中
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.feature as cfeature
import cartopy.io.shapereader as shapereader
shp_path = "D:/data2/china/china/province_9south.shp"#切記路徑一定要英文,血的教訓?。?!
fig = plt.figure(figsize=(6,8)) #注意畫布大小
proj = ccrs.PlateCarree()#創(chuàng)建投影,選擇cartopy的默認投影
ax = fig.subplots(1, 1, subplot_kw={'projection': proj}) #子圖
extent = [105, 133, 15, 45]#限定繪圖范圍
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
ax.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj,facecolor='none',edgecolor='k',linewidth=1)
ax.set_extent(extent, crs=proj)
#添加其他要素_中國地圖
ax.add_feature(cfeature.OCEAN.with_scale('50m'))
ax.add_feature(cfeature.LAND.with_scale('50m'))
ax.add_feature(cfeature.RIVERS.with_scale('50m'))
ax.add_feature(cfeature.LAKES.with_scale('50m'))
left, bottom, width, height = 0.67, 0.16, 0.23, 0.27#南海小地圖大小
ax2 = fig.add_axes([left, bottom, width, height], projection=proj)
ax2.add_geometries(shapereader.Reader(shp_path).geometries(), crs=proj, facecolor='none',edgecolor='k',linewidth=1)
ax2.set_extent([105, 125, 0, 25])#注意南海小地圖的范圍
#添加其他要素_南海小地圖
ax2.add_feature(cfeature.OCEAN.with_scale('50m'))
ax2.add_feature(cfeature.LAND.with_scale('50m'))
ax2.add_feature(cfeature.RIVERS.with_scale('50m'))
ax2.add_feature(cfeature.LAKES.with_scale('50m'))
添加圖片作為背景
方法一
使用cartopy的add_image方法,這里以添加osm在線地圖的圖片為例子
imagery = OSM()
ax.add_image(imagery, 4)#四為影像級別
完整代碼如下
import cartopy.crs as ccrs
import cartopy.feature as cfeat
from cartopy.io.shapereader import Reader
import matplotlib.pyplot as plt
from matplotlib.image import imread
from cartopy.io.img_tiles import OSM
def create_map():
# --設(shè)置shp路徑,數(shù)據(jù)集已公開
shp_path = 'D:/data2/china/china/province_9south.shp'
# --設(shè)置tif路徑,數(shù)據(jù)集已公開
tif_path = 'D:/data2/china/china/NE1_50M_SR_W.tif'
# --創(chuàng)建畫圖空間
proj = ccrs.PlateCarree() # 創(chuàng)建坐標系
fig = plt.figure(figsize=(6, 8)) # 創(chuàng)建頁面
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
# --設(shè)置地圖屬性
provinces = cfeat.ShapelyFeature(Reader(shp_path).geometries(),proj, edgecolor='k',facecolor='none')
# --加載省界線
ax.add_feature(provinces, lw=0.6, zorder=2)
ax.set_extent([105, 133, 15, 45]) #可根據(jù)需求自行定義
#添加osm圖片
imagery = OSM()
ax.add_image(imagery, 4)#四為影像級別
ax = create_map()
plt.show()
方法二
添加圖片所使用的第二種方法是 ax.imshow,是基于matplotlib的,這里以加載地形圖圖片為例
ax.imshow(imread(tif_path),extent=[-180, 180, -90, 90])注意范圍
繪制的完整代碼如下:
import cartopy.crs as ccrs
import cartopy.feature as cfeat
from cartopy.io.shapereader import Reader
import matplotlib.pyplot as plt
from matplotlib.image import imread
def create_map():
# --設(shè)置shp路徑,數(shù)據(jù)集已公開
shp_path = 'D:/data2/china/china/province_9south.shp'
# --設(shè)置tif路徑,數(shù)據(jù)集已公開
tif_path = 'D:/data2/china/china/NE1_50M_SR_W.tif'
# --創(chuàng)建畫圖空間
proj = ccrs.PlateCarree() # 創(chuàng)建坐標系
fig = plt.figure(figsize=(6, 8)) # 創(chuàng)建頁面
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
# --設(shè)置地圖屬性
provinces = cfeat.ShapelyFeature(Reader(shp_path).geometries(),proj, edgecolor='k',facecolor='none')
# --加載省界線
ax.add_feature(provinces, lw=0.6, zorder=2)
ax.set_extent([105, 133, 15, 45]) #可根據(jù)需求自行定義
# ax.stock_img() ##可直接使用低分辨率背景
# --加載高分辨率地形
ax.imshow(imread(tif_path),extent=[-180, 180, -90, 90])
ax = create_map()
plt.show()
你可以試試結(jié)合上述所講的內(nèi)容,做出一副這樣的地圖
示例代碼如下:
import cartopy.crs as ccrs
import cartopy.feature as cfeat
from cartopy.io.shapereader import Reader
import matplotlib.pyplot as plt
from matplotlib.image import imread
def create_map():
# --設(shè)置shp路徑,數(shù)據(jù)集已公開
shp_path = 'D:/data2/china/china/province_9south.shp'
# --設(shè)置tif路徑,數(shù)據(jù)集已公開
tif_path = 'D:/data2/china/china/NE1_50M_SR_W.tif'
# --創(chuàng)建畫圖空間
proj = ccrs.PlateCarree() # 創(chuàng)建坐標系
fig = plt.figure(figsize=(6, 8)) # 創(chuàng)建頁面
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
# --設(shè)置地圖屬性
provinces = cfeat.ShapelyFeature(Reader(shp_path).geometries(),proj, edgecolor='k',facecolor='none')
# --加載省界線
ax.add_feature(provinces, lw=0.6, zorder=2)
ax.set_extent([105, 133, 15, 45]) #可根據(jù)需求自行定義
# ax.stock_img() ##可直接使用低分辨率背景
# --加載高分辨率地形
ax.imshow(imread(tif_path),origin='upper', transform=proj,extent=[-180, 180, -90, 90])
# --設(shè)置網(wǎng)格點屬性
gl = ax.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,linewidth=1.2,color='k',alpha=0.5,linestyle='--')
# --設(shè)置南海子圖
left, bottom, width, height = 0.67, 0.16, 0.23, 0.27
ax2 = fig.add_axes([left, bottom, width, height], projection=proj)
ax2.add_feature(provinces, linewidth=0.6, zorder=2)
ax2.set_extent([105, 125, 0, 25])
# ax2.stock_img() ##可直接使用低分辨率背景
# --加載高分辨率地形
ax2.imshow(imread(tif_path),origin='upper',transform=proj,extent=[-180, 180, -90, 90])
return ax
ax = create_map()
plt.show()
注:本例教程參考至和鯨大佬【大自然搬運工】,針對大佬的代碼做了一些簡化方便大家理解;大佬繪制經(jīng)緯網(wǎng)好像使用的是matplotlib庫,與我之前所講述的cartopy庫繪制不一樣。原文章如下:文章來源:http://www.zghlxwxcb.cn/news/detail-460727.html
https://www.heywhale.com/mw/project/5f3c95a3af3980002cbf560b
學習心得
本文作為基礎(chǔ)入門教程就寫到這里吧,這幾天學習強度有點大了。在本文的學習過程中,我在和鯨社區(qū)找到了大量優(yōu)質(zhì)的學習博文,十分建議大家可以去看一看,同時以也才cartopy的文檔里得到了非常多的幫助,里面還有很多地圖的繪制方式,如果有機會,我希望我可以學習一下。文章來源地址http://www.zghlxwxcb.cn/news/detail-460727.html
和鯨社區(qū)
https://www.heywhale.com/home
cartopyAPI參考
https://scitools.org.uk/cartopy/docs/latest/reference/generated/cartopy.mpl.geoaxes.GeoAxes.html#cartopy.mpl.geoaxes.GeoAxes.add_feature
cartopy更多地圖
https://scitools.org.uk/cartopy/docs/latest/gallery/index.html
數(shù)據(jù)下載
行政區(qū)劃_省界.shp
https://wwc.lanzouw.com/iQ4TT0843gpc
GMT 中文社區(qū)提供的數(shù)據(jù)
https://wwc.lanzouw.com/iYLrc0843gvi
地形圖圖片
https://wwc.lanzouw.com/ipPrM0843g8f
參考文檔
https://zhajiman.github.io/post/cartopy_introduction/
https://mp.weixin.qq.com/s/FKNBOD2Yo4sawWTO76zZgA
https://mp.weixin.qq.com/s/m4Ao0--o1umSICEWO9UlKw
https://mp.weixin.qq.com/s/oe2ncVdqfdjaPSDZ2-YLQg
https://cloud.tencent.com/developer/article/1790590
https://mp.weixin.qq.com/s/wbyrkmVoaWgz6MdBI_6BZg
https://mp.weixin.qq.com/s/5RiuM2AQxNIvgNcLf5fCDw
https://mp.weixin.qq.com/s/FGCPIoiC5OUkGGf_IreWZQ
https://www.cnblogs.com/youxiaogang/p/14247184.html
https://www.heywhale.com/mw/project/629eefe52d8168866e54adc9
https://www.heywhale.com/mw/project/5f1a4df794d484002d2db14a
https://www.heywhale.com/mw/project/5f3c95a3af3980002cbf560b
https://blog.csdn.net/m0_37362454/article/details/81511427
https://www.osgeo.cn/pygis/cartopy-feature.html
https://vimsky.com/examples/detail/python-module-cartopy.mpl.ticker.html
https://scitools.org.uk/cartopy/docs/v0.14/matplotlib/feature_interface.html
https://mp.weixin.qq.com/s/jpZOpnFvMwi4ZTafflXIzw
https://gnss.help/2018/04/24/cartopy-gallery/index.html
https://blog.csdn.net/weixin_42372313/article/details/113572786
https://scitools.org.uk/cartopy/docs/latest/index.html
https://scitools.org.uk/cartopy/docs/v0.13/matplotlib/geoaxes.html
https://waterhackweek.github.io/visualization/04-geopandas-and-cartopy/
https://scitools.org.uk/cartopy/docs/v0.14/matplotlib/feature_interface.html
https://mp.weixin.qq.com/s/ASV-VI6gfbea90vtJbdpIw
到了這里,關(guān)于Cartopy繪圖入門指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!