在模仿中精進(jìn)數(shù)據(jù)可視化07:星球研究所大壩分布可視化

添加微信號"CNFeffery"加入技術(shù)交流群
?本文完整代碼及數(shù)據(jù)已上傳至我的
?Github倉庫https://github.com/CNFeffery/FefferyViz
1 簡介
在星球研究所最近的《10萬座大壩的誕生!》一文中,作者們利用豐富的數(shù)據(jù)可視化手段對我國及世界大型水壩工程的發(fā)展分布情況進(jìn)行了分析展示,而我尤其喜愛其中的一幅作品:

這是一幅信息量豐富且難度較大的數(shù)據(jù)可視化作品,因為它混合了地理信息可視化與象形柱狀圖,使得繪制它需要多方面的數(shù)據(jù)可視化知識。
復(fù)刻有挑戰(zhàn)性的數(shù)據(jù)可視化作品正是我這個系列文章的主旨,在今天的文章中,我就將基于Python,教大家如何還原出這幅作品中的主要視覺元素。
2 復(fù)刻過程
首先,按照我們這個系列文章的傳統(tǒng),先來對原作品中的視覺元素進(jìn)行剖析,進(jìn)而構(gòu)思出“逐一攻破”的方法:
2.1 拆解主要視覺元素
「半球部分」
這幅作品首先映入眼簾的自然是其上方對稱布局的兩個半球圖像,要繪制它們其實比較簡單,我們可以利用地球「正射投影」(Orthographic projection),分別選定不同的中央經(jīng)緯度,便可得到左右不同視角下的半球。

「象形柱狀圖部分」
原作品中下方部分的象形柱狀圖也是非常的形象生動切合主題,通過觀察可以發(fā)現(xiàn)每個大壩logo代表數(shù)值200,而末尾不足200的部分就按照余數(shù)/200的「透明度」進(jìn)行渲染,配合右下角的圖例,幫助讀者快速解讀出信息,這實現(xiàn)起來也不難,我將會使用matplotlib的相關(guān)API配合循環(huán)語句來實現(xiàn)logo圖片的嵌入。
「其余輔助視覺元素」
除了上面介紹的兩部分視覺主體之外,其余的部分都主要是些文字或符號之類的小部件,模仿起來比較簡單(上方地圖的國家名稱標(biāo)注部分用代碼自動化的方式反而更費事,因此本文模仿過程略去這部分),可以明顯看出的是其主要的標(biāo)題等文字內(nèi)容主要使用了「思源宋體」。
摸清楚要做的內(nèi)容之后,下面讓我們開始吧!
2.2 半球部分的制作
「正射投影」部分,我選擇使用cartopy.ccrs內(nèi)置的Orthographic(),通過傳入中央經(jīng)緯度,即可得到期望的半球面:

我們利用mpl_toolkits.axes_grid1.inset_locator中的inset_axes()將兩個半球各自對應(yīng)的axe對象插入到主體axe中,再利用cartopy的add_geometries進(jìn)行矢量元素的疊加和色彩映射即可,我已經(jīng)在數(shù)據(jù)中算好了歸一化數(shù)值方便色彩映射,以左半球為例:
fig,?ax?=?plt.subplots(figsize=(5.4,?8.1))
#?構(gòu)建左半球圖像
map_left?=?inset_axes(ax,?width='100%',?height='100%',?
??????????????????????bbox_to_anchor=(0.19,?0.58,?0.26,?0.26),
??????????????????????bbox_transform=ax.transAxes,
??????????????????????axes_class=cartopy.mpl.geoaxes.GeoAxes,?
??????????????????????axes_kwargs=dict(map_projection=crs_left))
#?添加陸地面并設(shè)置顏色
map_left.add_feature(cfeature.NaturalEarthFeature('physical',?'land',?'110m',?
????????????????????????????????????????????edgecolor='none',?
????????????????????????????????????????????facecolor='#d9d9d9'))
#?為不同國家添加面要素并按照歸一化數(shù)值上色
for?country?in?["美國",?"墨西哥",?"巴西"]:
????map_left.add_geometries(data.query('國家?==?@country').geometry,
????????????????????????????crs=ccrs.PlateCarree(),
????????????????????????????facecolor=custom_cmap(data.query('國家==@country').iat[0,?-2]),
????????????????????????????zorder=999)
#?設(shè)置畫框樣式
map_left.spines['geo'].set_linewidth(0.6)
map_left.spines['geo'].set_color('#d9d9d9')

這樣我們就完成了兩個半球部分的制作,順便配合matplotlib中的text()、參數(shù)fontproperties以及matplotlib.font_manager來基于思源宋體添加標(biāo)題:

2.3 象形柱狀圖部分的制作
介紹完「半球」地圖部分,我們接著來制作「象形柱狀圖」部分,這部分的核心內(nèi)容是使用matplotlib.offsetbox下的OffsetImage()、AnnotationBbox(),配合matplotlib自帶的add_artist(),向現(xiàn)有的圖床中插入外部圖片(這里的logo圖片是我通過軟件手繪的~)。
其中OffsetImage()傳入圖片數(shù)組變量、縮放比例以及透明度;AnnotationBbox()用于調(diào)整所插入圖片在圖中的位置,遵守一行10個logo的最大布局?jǐn)?shù)量,略微構(gòu)思一下嵌套循環(huán)過程,微調(diào)位置參數(shù),即可在前面的基礎(chǔ)上,得到下面的圖像:

而右下角圖例中的第一個logo上下漸變的效果其實是配合numpy數(shù)組,從上往下線性地降低rgba第四個通道的透明度值得到了,非常的容易~

而圖中其他的小元素譬如各種文字就不贅述了,無非是text()復(fù)制粘貼改改參數(shù)而已,對完整過程感興趣的朋友可以在文章開頭的Github倉庫中找到對應(yīng)數(shù)據(jù)和代碼~
以上就是本文的全部內(nèi)容,歡迎在評論區(qū)與我進(jìn)行討論~

加入知識星球【我們談?wù)摂?shù)據(jù)科學(xué)】
300+小伙伴一起學(xué)習(xí)!
· 推薦閱讀?·
Python+Dash快速web應(yīng)用開發(fā):回調(diào)交互篇(上)
Python+Dash快速web應(yīng)用開發(fā)——頁面布局篇
