常用的6種繪制地圖的方法

今天來講一講在日常工作生活中我常用的幾種繪制地圖的方法衡创,下面我將介紹下面這些可視化庫的地圖繪制方法,當(dāng)然繪制漂亮的可視化地圖還有很多優(yōu)秀的類庫,沒有辦法一一列舉

pyecharts诈闺、plotly菜枷、folium称鳞、bokeh涮较、basemap、geopandas冈止、cartopy

Boken

首先我們先介紹 Boken 繪制地圖的方法

Bokeh 支持創(chuàng)建基本地圖可視化和基于處理地理數(shù)據(jù)的地圖可視化

畫一張世界地圖

frombokeh.plottingimportfigure,?show

frombokeh.tile_providersimportCARTODBPOSITRON,?get_provider

frombokeh.ioimportoutput_notebook

output_notebook()

tile_provider?=?get_provider(CARTODBPOSITRON)

p?=?figure(x_range=(-2000000,6000000),?y_range=(-1000000,7000000),

x_axis_type="mercator",?y_axis_type="mercator")

p.add_tile(tile_provider)

show(p)

再畫一張中國地圖看看

frombokeh.plottingimportcurdoc,?figure

frombokeh.modelsimportGeoJSONDataSource

frombokeh.ioimportshow

#?讀入中國地圖數(shù)據(jù)并傳給GeoJSONDataSource

withopen("china.json",?encoding="utf8")asf:

geo_source?=?GeoJSONDataSource(geojson=f.read())

#?設(shè)置一張畫布

p?=?figure(width=500,?height=500)

#?使用patches函數(shù)以及geo_source繪制地圖

p.patches(xs='xs',?ys='ys',?source=geo_source)

show(p)

我們通過 GEO 地理數(shù)據(jù)來繪制地圖同樣非常方便狂票,但是地圖看起來有一些單調(diào),我們把不同的省份繪制成不同的顏色來看看

withopen("china.json",?encoding="utf8")asf:

data?=?json.loads(f.read())

#?判斷是不是??北京地區(qū)數(shù)據(jù)

defisBeijing(district):

if'beijing'indistrict['properties']['woe-name'].lower():

returnTrue

returnFalse

#?data['features']?=?list(filter(isInLondon,?data['features']))

#?過濾數(shù)據(jù)

#?為每一個(gè)地區(qū)增加一個(gè)color屬性

foriinrange(len(data['features'])):

data['features'][i]['properties']['color']?=?['red','blue','yellow','orange','gray','purple'][i?%6]

data['features'][i]['properties']['number']?=?random.randint(0,20_000)

geo_source?=?GeoJSONDataSource(geojson=json.dumps(data))

p?=?figure(width=500,?height=500,?tooltips="@name,?number:?@number")

p.patches(xs='xs',?ys='ys',?fill_alpha=0.7,

line_color='white',

line_width=0.5,

color="color",#?增加顏色屬性熙暴,這里的"color"對(duì)應(yīng)每個(gè)地區(qū)的color屬性

source=geo_source)

p.axis.axis_label?=None

p.axis.visible?=False

p.grid.grid_line_color?=None

show(p)

可以看到已經(jīng)有內(nèi)味了闺属,唯一美中不足的就是南海的十三段線沒有展示出來

geopandas

GeoPandas 是基于 Pandas 的地圖可視化工具,其數(shù)據(jù)結(jié)構(gòu)完全繼承自 Pandas周霉,對(duì)于熟悉潘大師的同學(xué)來說還是非常友好的

還是先畫一張世界地圖

importpandasaspd

importgeopandas

importmatplotlib.pyplotasplt

%matplotlib?inline

world?=?geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))

world.plot()

plt.show()

這也是 geopandas 官網(wǎng)上的經(jīng)典圖片掂器,可以看到非常簡單,除去 import 代碼俱箱,僅僅三行国瓮,就完成了地圖的繪制

下面我們繼續(xù)繪制中國地圖,這次我們加上九段線信息

china_nine?=?geopandas.read_file(r"geojson/九段線GS(2019)1719號(hào).geojson")

china?=?geopandas.read_file('china-new.json')

fig,?ax?=?plt.subplots(figsize=(12,8),dpi=80)

ax?=?china.plot(ax=ax,?column='number')

ax?=?china_nine.plot(ax=ax)

plt.show()

我們復(fù)用了前面處理的 china.json 數(shù)據(jù)狞谱,里面的 number 字段是隨機(jī)生成的測試數(shù)據(jù)乃摹,效果與 Bokeh 不相上下

plotly

接下來我們介紹 plotly,這也是一個(gè)非常好用的 Python 可視化工具跟衅,如果要繪制地圖信息孵睬,我們需要安裝如下依賴

!pip?install?geopandas==0.3.0

!pip?install?pyshp==1.2.10

!pip?install?shapely==1.6.3

接下來我們先繪制一個(gè)世界地圖

importplotly.graph_objectsasgo

fig?=?go.Figure(go.Scattermapbox(

mode?="markers+lines",

lon?=?[10,20,30],

lat?=?[10,20,30],

marker?=?{'size':10}))

fig.add_trace(go.Scattermapbox(

mode?="markers+lines",

lon?=?[-50,-60,40],

lat?=?[30,10,-20],

marker?=?{'size':10}))

fig.update_layout(

margin?={'l':0,'t':0,'b':0,'r':0},

mapbox?=?{

'center':?{'lon':113.65000,'lat':34.76667},

'style':"stamen-terrain",

'center':?{'lon':-20,'lat':-20},

'zoom':1})

fig.show()

這里我們使用底層 API?plotly.graph_objects.Choroplethmapbox?來繪制

下面我們繼續(xù)繪制中國地圖,使用一個(gè)高級(jí) API?plotly.express.choropleth_mapbox

import pandas aspd

importplotly.expressaspx

importnumpyasnp

importjson

withopen(r"china_province.geojson",?encoding='utf8')asf:

provinces_map?=?json.load(f)

df?=?pd.read_csv(r'data.csv')

df.確診?=?df.確診.map(np.log)

fig?=?px.choropleth_mapbox(

df,

geojson=provinces_map,

color='確診',

locations="地區(qū)",

featureidkey="properties.NL_NAME_1",

mapbox_style="carto-darkmatter",

color_continuous_scale='viridis',

center={"lat":37.110573,"lon":106.493924},

zoom=3,

)

fig.show()

可以看出繪制出的交互式地圖還是非常漂亮的伶跷,不過渲染速度有些感人掰读,這個(gè)就看個(gè)人的需求了,如果你對(duì)渲染速度有要求撩穿,那么 Ployly 可能不是最好的選擇~

Cartopy/Basemap

之所以把這兩個(gè)庫放到一起磷支,是因?yàn)樗麄兌际腔?Matplotlib 之上的谒撼,而隨著 Python2 的不再維護(hù)食寡,Basemap 也被 Matplotlib 放棄,Cartopy 隨之轉(zhuǎn)正廓潜,下面我們主要介紹 Cartopy 工具

Cartopy 利用了強(qiáng)大的 PROJ.4抵皱、NumPy 和 Shapely 庫,并在 Matplotlib 之上構(gòu)建了一個(gè)編程接口辩蛋,用于創(chuàng)建發(fā)布高質(zhì)量的地圖

先來繪制一個(gè)世界地圖

%matplotlib?inline

importcartopy.crsasccrs

importmatplotlib.pyplotasplt

ax?=?plt.axes(projection=ccrs.PlateCarree())

ax.coastlines()

plt.show()

這是一個(gè) cartopy 繪制的非常經(jīng)典且常見的世界地圖呻畸,形式比較簡單,下面我們?cè)鰪?qiáng)該地圖

importdatetime

importmatplotlib.pyplotasplt

importcartopy.crsasccrs

fromcartopy.feature.nightshadeimportNightshade

fig?=?plt.figure(figsize=(10,5))

ax?=?fig.add_subplot(1,1,1,?projection=ccrs.PlateCarree())

date?=?datetime.datetime(2021,12,2,21)

ax.set_title(f'Night?time?shading?for{date}')

ax.stock_img()

ax.add_feature(Nightshade(date,?alpha=0.2))

plt.show()

我們通過上面的代碼悼院,繪制了當(dāng)前時(shí)間世界晝夜圖伤为,還是很強(qiáng)的

下面我們繼續(xù)繪制中國地圖

importcartopy.io.shapereaderasshpreader

importnumpyasnp

importmatplotlib.pyplotasplt

importcartopy.crsasccrs

importcartopy.featureascfeature

fromcartopy.mpl.gridlinerimportLONGITUDE_FORMATTER,?LATITUDE_FORMATTER

fromcartopy.mpl.tickerimportLongitudeFormatter,?LatitudeFormatter

importcartopy.io.shapereaderasshapereader

importmatplotlib.tickerasmticker

#從文件中加載中國區(qū)域shp

shpfile?=?shapereader.Reader(r'ne_10m_admin_0_countries_chn\ne_10m_admin_0_countries_chn.shp')

#?設(shè)置?figure?大小

fig?=?plt.figure(figsize=[8,5.5])

#?設(shè)置投影方式并繪制主圖

ax?=?plt.axes(projection=ccrs.PlateCarree(central_longitude=180))

ax.add_geometries(

shpfile.geometries(),

ccrs.PlateCarree())

ax.set_extent([70,140,0,55],crs=ccrs.PlateCarree())

plt.show()

使用 cartopy 繪制地圖最大的特點(diǎn)就是靈活度高,那么相對(duì)應(yīng)的代價(jià)就是編寫代碼也會(huì)更難一些,比如如果想要給不同省份填充不同顏色绞愚,我們需要編寫的代碼就有點(diǎn)多

importmatplotlib.patchesasmpatches

importmatplotlib.pyplotasplt

frommatplotlib.font_managerimportFontProperties

importshapely.geometryassgeom

importcartopy.crsasccrs

importcartopy.io.shapereaderasshpreader

font?=?FontProperties(fname=r"c:\windows\fonts\simsun.ttc",?size=14)

defsample_data():

#????lons?=?[110,?115,?120,?122,?124?]

lons?=?[124,122,120,115,110]

lats?=?[33,32,28,30,28]

returnlons,?lats

#ax?=?plt.axes([0,?0,?1,?1],?projection=ccrs.LambertConformal())

ax?=?plt.axes(projection=ccrs.PlateCarree())

ax.set_extent([70,140,0,55],crs=ccrs.Geodetic())

shapename?='admin_1_states_provinces'

states_shp?=?shpreader.natural_earth(resolution='10m',?category='cultural',?name=shapename)

lons,?lats?=?sample_data()

#?to?get?the?effect?of?having?just?the?states?without?a?map?"background"

#?turn?off?the?outline?and?background?patches

ax.background_patch.set_visible(False)

ax.outline_patch.set_visible(False)

plt.title(u'China?Province?Level',?fontproperties=font)

#?turn?the?lons?and?lats?into?a?shapely?LineString

track?=?sgeom.LineString(zip(lons,?lats))

track_buffer?=?track.buffer(1)

forstateinshpreader.Reader(states_shp).geometries():

#?pick?a?default?color?for?the?land?with?a?black?outline,

#?this?will?change?if?the?storm?intersects?with?our?track

facecolor?=?[0.9375,0.9375,0.859375]

edgecolor?='black'

ifstate.intersects(track):

facecolor?='red'

elifstate.intersects(track_buffer):

facecolor?='#FF7E00'

ax.add_geometries([state],?ccrs.PlateCarree(),

facecolor=facecolor,?edgecolor=edgecolor)

#?make?two?proxy?artists?to?add?to?a?legend

direct_hit?=?mpatches.Rectangle((0,0),1,1,?facecolor="red")

within_2_deg?=?mpatches.Rectangle((0,0),1,1,?facecolor="#FF7E00")

labels?=?[u'省份level1',

'省份level2']

plt.legend([direct_hit,?within_2_deg],?labels,

loc='lower?left',?bbox_to_anchor=(0.025,-0.1),?fancybox=True,?prop=font)

ax.figure.set_size_inches(14,9)

plt.show()

folium

folium 是建立在 Python 生態(tài)系統(tǒng)的數(shù)據(jù)應(yīng)用能力和 Leaflet.js 庫的映射能力之上的高級(jí)地圖繪制工具叙甸,通過 Python 操作數(shù)據(jù),然后在 Leaflet 地圖中可視化位衩,可以靈活的自定義繪制區(qū)域裆蒸,并且展現(xiàn)形式更加多樣化

首先是三行代碼繪制世界地圖

importfolium

#?define?the?world?map

world_map?=?folium.Map()

#?display?world?map

world_map

接下來繪制中國地圖

#?繪制邊界

importjson

df?=?pd.read_csv(r'plotly-choropleth-mapbox-demo-master/data.csv')

#?read?china?border?

withopen(r"plotly-choropleth-mapbox-demo-master/china_province.geojson",?encoding='utf8')asf:

china?=?json.load(f)

chn_map?=?folium.Map(location=[40,100],?zoom_start=4)

folium.Choropleth(

geo_data=china,

name="choropleth",

data=df,

columns=["地區(qū)","確診"],

key_on="properties.NL_NAME_1",

fill_color="YlGn",

fill_opacity=0.7,

line_opacity=0.2,

legend_name="新冠確診",

).add_to(chn_map)

folium.LayerControl().add_to(chn_map)

chn_map

作為專業(yè)地圖工具,不僅渲染速度快糖驴,自定義程度也是非常高的僚祷,值得使用嘗試

PyEcharts

最后我們介紹 PyEcharts,這款國產(chǎn)的精良可視化工具?

繪制世界地圖

frompyechartsimportoptionsasopts

frompyecharts.chartsimportMap

frompyecharts.fakerimportFaker

c?=?(

Map()

.add("測試數(shù)據(jù)",?[list(z)forzinzip(Faker.country,?Faker.values())],"world")

.set_series_opts(label_opts=opts.LabelOpts(is_show=False))

.set_global_opts(

title_opts=opts.TitleOpts(title="Map-世界地圖"),

visualmap_opts=opts.VisualMapOpts(max_=200),

)

)

c.render_notebook()

通過 Pyecharts 繪制地圖的一個(gè)好處就是不需要處理 GEO 文件贮缕,我們直接出入國家名稱辙谜,就可以自動(dòng)匹配到地圖上,非常方便

再繪制中國地圖

c?=?(

Map()

.add("測試數(shù)據(jù)",?[list(z)forzinzip(Faker.provinces,?Faker.values())],"china")

.set_global_opts(

title_opts=opts.TitleOpts(title="Map-VisualMap(中國)"),

visualmap_opts=opts.VisualMapOpts(max_=200,?is_piecewise=True),

)

)

c.render_notebook()

我們只需要把參數(shù)替換成 ”china“ 就可方便的繪制中國地圖跷睦,真的很給力筷弦,當(dāng)然對(duì)于 Pyecharts 還有很多種玩法,就不一一介紹了

綜合上面的示例抑诸,我們可以看出烂琴,?Pyecharts?繪制地圖最為簡單,非常適合新手學(xué)習(xí)使用蜕乡;而?folium?和cartopy?則勝在自由度上奸绷,它們作為專業(yè)的地圖工具,留給了使用者無限可能层玲;至于?Plotly?和?Bokeh?則屬于更高級(jí)的可視化工具号醉,它們勝在畫質(zhì)更加優(yōu)美,API?調(diào)用也更加完善

今天我們介紹了幾種比較常用的繪制地圖的類庫辛块,每一個(gè)工具都有其優(yōu)缺點(diǎn)畔派,我們只需要在選擇的時(shí)候,明確目標(biāo)润绵,用心探索就好

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末线椰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子尘盼,更是在濱河造成了極大的恐慌憨愉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卿捎,死亡現(xiàn)場離奇詭異配紫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)午阵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門躺孝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事植袍∥焙埽” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵奋单,是天一觀的道長锉试。 經(jīng)常有香客問我,道長览濒,這世上最難降的妖魔是什么呆盖? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮贷笛,結(jié)果婚禮上应又,老公的妹妹穿的比我還像新娘。我一直安慰自己乏苦,他們只是感情好株扛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著汇荐,像睡著了一般洞就。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掀淘,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天旬蟋,我揣著相機(jī)與錄音,去河邊找鬼革娄。 笑死倾贰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拦惋。 我是一名探鬼主播匆浙,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼厕妖!你這毒婦竟也來了首尼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤叹放,失蹤者是張志新(化名)和其女友劉穎饰恕,沒想到半個(gè)月后挠羔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體井仰,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年破加,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俱恶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖合是,靈堂內(nèi)的尸體忽然破棺而出了罪,到底是詐尸還是另有隱情,我是刑警寧澤聪全,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布泊藕,位于F島的核電站,受9級(jí)特大地震影響难礼,放射性物質(zhì)發(fā)生泄漏娃圆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一蛾茉、第九天 我趴在偏房一處隱蔽的房頂上張望讼呢。 院中可真熱鬧,春花似錦谦炬、人聲如沸悦屏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽础爬。三九已至,卻和暖如春吼鳞,著一層夾襖步出監(jiān)牢的瞬間幕帆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國打工赖条, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留失乾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓纬乍,卻偏偏與公主長得像碱茁,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仿贬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容