氣象繪圖|最全的matplotlib colorbar設置,總有一款能滿足你!

2022-01-24 氣象匯

本節提要:關於一些不常見的colorbar的仿製:彎曲與環形的colorbar、兩端分離的colorbar、收縮colorbar的主副刻度、雙刻度列colorbar、截取與拼接cmap、外部顏色引入cmaps與palettable庫包、特別的格式定製、levels等距而colorbar刻度距離不等距、其他類型的偽colorbar、使刻度側的框線與colorbar柱體分離。

上面提到的這些非常規的colorbar,主要依據的原樣圖是我平時偶然發現,或與其他大佬交流時,覺得還不錯的圖片,但是還沒有在matplotlib中發現繪製技法,或對新手來說不太容易掌握的colorbar技巧。本期內容比較多,基本上掏空了我在colorbar方面的全部存貨。希望各位讀者喜歡,多多點讚轉發。

一、彎曲與環形的colorbar

這是我很久之前在氣象家園上看到一個朋友提的問題了。也不知他解決沒有,我又去翻找了下,大概帖子已經沉底,只能在這裡寫一下了。

colorbar函數好像並沒有給出能夠改變其樣式的參數,所以,想要直接簡單的通過修改參數來讓他變為彎曲的樣式就非常困難了。(也不排除我眼瞎官網手冊沒看到)所以我們只能取巧了,假造一個colorbar(以下省稱cbar)。這一節推送裡的很多cbar其實都是偽cbar,怎麼理解呢?

我們通常生成cbar,一般要將等值線圖的代號傳進去,比如:

ac=ax.contourf(...)fig.colorbar(ac)

這種直接傳入的方法我稱之為有源cbar,指的是顏色映射直接指向原圖,不存在任何偏差,數值與顏色絕對與原圖相匹配。但是顯然,我們不能這樣掰彎一個有源的cbar,原因見前。所以我們要按照原圖的colormap和levels來偽造一個cbar,使其在視覺效果上變成一個彎曲的cbar。

首先前面的程序直到畫等值線都是走流程。這裡只擷取核心代碼段:

from matplotlib import cmac=ax.contourf(levels=...,cmap='RdBu_r') #省略部分內容ac.levelscmap=cm.get_cmap('RdBu_r',len(cs.levels)-1) #獲得等值線填色圖的色條對應分級angle=np.arange(0,0.5*np.pi,0.5*np.pi/(len(cs.levels)-1))radius=np.array([2]*(len(ac.levels)-1))cmaps=cmap(range(len(cs.levels)-1))ax1.set_theta_offset(np.pi/2)ax1.bar(angle,radius,width=0.5*np.pi/11,color=cmaps,align='center')for i,x,y in zip(cs.levels,angle,radius):    ax1.text(x-0.1,y+0.17,i,fontsize=3)ax1.text(0.9,2.6,'氣溫:℃',fontsize=4)

ax1是個極坐標的子圖,在最底層,我們疊加的地圖是另一個ax,在上層,利用上層的地圖遮住下面。然後在視覺上形成彎曲的cbar。在生成angle時我們只用了0.5π,一個圓的周長是2π,所以我們的彎曲cbar只有四分之一。

利用這個方式還可以完成下面這個圖的cbar:

不過要修改x軸的劃分區域,變為2π,還要限制ylim使其中心被掏空。

另外,還可以用劉大成《matplotlib精進》p28裡提到的用楔形繪製圓環的辦法完成彎曲cbar的繪製。

二、兩端分離的colorbar

這個的仿製的緣起是另一個公號的編輯給我看了一張圖,我覺得還比較好看,所以專門取出來看看。這個圖的兩端的尖角與主體是分離的。我嘗試翻了官網文檔,好像不能實現。(也有可能我過年豬油吃多了)那就是又在逼我偽造cbar了。

完整代碼如下:

import numpy as npimport xarray as xrimport matplotlib.pyplot as pltimport matplotlib.path as mpathimport matplotlib as mplfrom matplotlib import cm,colorsfrom matplotlib.patches import Rectangleimport cartopy.crs as ccrsfrom cartopy.util import add_cyclic_pointfrom cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTERimport cartopy.feature as cfimport cartopy.io.shapereader as shpreaderplt.rcParams['font.sans-serif']=['SimHei']file=r'E:\aaaa\datanc\fnl_20190620_00_00.grib2'data=xr.open_dataset(file,engine='cfgrib',backend_kwargs={'filter_by_keys': {'typeOfLevel': 'surface'}})t=data['t']-278.15lat=data['latitude']lon=data['longitude']proj=ccrs.LambertConformal(central_longitude=105, central_latitude=35)reader = shpreader.Reader( r'F:\BaiduNetdiskDownload\MeteoInfo\MeteoInfo_Software\MeteoInfo\map\china.shp')provinces=cf.ShapelyFeature(reader.geometries(),crs=ccrs.PlateCarree(), edgecolor='k', facecolor='none',alpha=1,lw=0.5)extent=[80,130,10,60]fig=plt.figure(figsize=(1.5,1.5),dpi=800)ax=fig.add_axes([0,0.1,1,0.85],projection=proj)ax.add_feature(cf.COASTLINE.with_scale('50m'),lw=0.25)ax.add_feature(cf.OCEAN.with_scale('50m'),lw=0.5)ax.add_feature(cf.LAND.with_scale('50m'),lw=0.5,edgecolor='none')ax.add_feature(cf.RIVERS.with_scale('50m'),lw=0.25)ax.add_feature(provinces, linewidth=0.3)ax.spines['geo'].set_linewidth(0.5)ax.set_extent(extent)ax2=fig.add_axes([0.054,0,0.892,0.1])ax2.tick_params(axis='both',which='major',direction='in',width=0.5,length=0.5,labelsize=3)for i in['top','bottom','left','right']:    ax2.spines[i].set_linewidth(0.5)ac=ax.contourf(lon,lat,t,cmap='Spectral_r',levels=np.arange(-20,40,2),transform=ccrs.PlateCarree())ax2.set(xlim=(-3,30),ylim=(0,1))num=ac.levelscolormap=cm.get_cmap('Spectral_r',len(num)-1)cmaps=colormap(range(len(num)-1))camps=cmaps.tolist()for i,x,y,color in zip(range(len(num)-2),range(len(num)-2),[0.25]*(len(num)-2),cmaps[1:-1]):    rectangle=Rectangle([x,y],1,0.5,facecolor=color,                    alpha=1,                    edgecolor='none')    ax2.add_patch(rectangle)left=plt.Polygon(xy=[[-0.75,0.31], [-0.75, 0.69], [-2.5,0.5]], color=cmaps[0])right=plt.Polygon(xy=[[27.75,0.31],[27.75,0.69],[29.5,0.5]],color=cmaps[-1])ax2.add_patch(left)ax2.add_patch(right)ax2.axis('off')ax.set_title('分離colorbar',fontsize=7) 

因為想這個辦法只花了一個小時,肯定有些能簡略的地方或者更好的辦法,我這裡只是一個造假cbar的思路。

通過中間的一個for循環,我們將每個等級的色條以顏色polygon的方法按順序從左往右排列,變成一個視覺上的cbar,其實不是我們常規意義上的cbar。然後通過最後left、right兩個polygon來添加分離的兩頭小三角。

在for循環中cmap[ 1:-1]表示顏色列表中的[ 0 ]和[ -1 ]即首尾兩個顏色沒有參與中間柱形polygon的添加工作。這兩個顏色被賦予到left和right兩個polygon中了。

這一節指的是對colorbar的刻度進行修飾,一般來說,自動生成的cbar是黑色邊框的,刻度尺朝外的,字體大小也存在一定的問題。這裡簡單對其做個美化。我們以仿製plotnine庫包的cbar為例子。

cax=fig.add_axes([0.95,0.6,0.05,0.4])cmap=mpl.cm.viridisbounds=np.arange(0,100,1)norm=mpl.colors.BoundaryNorm(bounds, cmap.N)cbar=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),cax=cax)cbar.outline.set_color('none')cbar.ax.tick_params(which='both',direction='in',length=1,width=0.25,color='white',labelsize=2,left=True,pad=0.5)

cax這一步代表強制指定cbar擺放的位置,在傳入參數後,cbar只能擺放在這個子圖上,不會調參時東跑西跑了。

cbar.outline.set_color('none')表示將cbar的邊框顏色變為無。

ax.tick_parmas這句話,可以參考前面的推送文章中的關於刻度軸的內容:氣象繪圖加強版(四)—坐標名、刻度、軸。通過which這個參數,我們可以將主副刻度分別設置為相反的朝向等。這裡就不在贅述。

這裡提到了前面文章推送過的雙刻度列的cbar,上次推送很多地方沒有講完,這裡再提一次。並且用我們常用的雨量量級來做一個雙刻度cbar。首先製作一個單側刻度列的cbar:

import numpy as npimport matplotlib as mplimport matplotlib.pyplot as pltimport matplotlib.colors as mcolorsfig=plt.figure(figsize=(1.5,0.2),dpi=500)ax=fig.add_axes([0,0,1,0.5])colorlevel=[0.1,10.0,25.0,50.0,100.0,250.0,500.0]colordict=['#A6F28F','#3DBA3D','#61BBFF','#0000FF','#FA00FA','#800040']cmap=mcolors.ListedColormap(colordict)norm=mcolors.BoundaryNorm(colorlevel,cmap.N)fc=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),             cax=ax, orientation='horizontal',extend='both')fc.ax.tick_params(which='major',labelsize=3,direction='out',width=0.5,length=1)fc.outline.set_linewidth(0.3)

生成一個顏色條之後,進入下一步:

ax2=fc.axax2.xaxis.set_ticks_position('top')ax2.tick_params(labelsize=3,top=True,width=0.5,length=1)ax3=ax2.secondary_xaxis('bottom')ax3.tick_params(labelsize=3,width=0.5,length=1)ax3.spines['bottom'].set_bounds(0.1,500)ax3.set_xticks([40,120,210,290,380,460])ax3.set_xticklabels(['小雨','中雨','大雨','暴雨','大暴雨','特大暴雨'])ax3.spines['bottom'].set_linewidth(0.3)

這樣我們一方面就可以定量的分析各個雨級的mm值,又可以定性的分析各個雨級。還是比較實用的,當然,不一定只到500mm,這只是生成cbar時的限制的,你也可以改到1000。

請注意,在自己定製降水量色條時,間距是不相等的,但是新生成的ax3間距是相等的,所以會出現錯位,不過這不重要,只要視覺上過關即可。如果是自動生成的cbar,則不存在這樣的問題。

這個不是我想出來的,但也是一個比較少用的功能。即提取一個colormap的某一部分,或者將兩個colormap拼到一起。主要基於Creating Colormaps in Matplotlib這個Tutorials裡的一些demo。還參考了公眾號DQS小王的文章,以及氣象家園論壇ID為f_idled的用戶總結的經驗。

這裡只講講為什麼能截取和拼接。在第一和第二小節中,我們就提取過colormap,並將其劃分為levels的對應片段,並對每個polygon填色,實際上colormap就是一系列的色號拼接而成的一個數組。而在我們學習python中,列表list是切片操作的始祖。是數組就可以切片。數組可以切片,那麼colormap就可以截取與拼接。colormap的操作轉化為列表的操作。

這裡用DQS的例子做說明:

import numpy as npimport matplotlib as mplimport matplotlib.pyplot as pltfrom matplotlib.colors import ListedColormapcmap=mpl.cm.jet_rnewcolors=cmap(np.linspace(0,1,256))newcmap=ListedColormap(newcolors[125:])fig=plt.figure(figsize=(1.5,0.3),dpi=500)ax1=fig.add_axes([0,0,1,0.45])ax2=fig.add_axes([0,0.5,1,0.45])norm = mpl.colors.Normalize(vmin=0, vmax=10)fc1=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap='jet_r'),cax=ax1, orientation='horizontal',extend='both')fc2=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=newcmap),cax=ax2, orientation='horizontal',extend='both')for i in [fc1,fc2]:    i.ax.tick_params(labelsize=3,width=0.5,length=0.5)    i.outline.set_linewidth(0.5)

可以看出,暖色部分基本被截去了。更多的內容大家可以參考提到的作者的原文章,這裡不再展開(其實是我實在打不動字了)。

六、外部顏色引入cmaps與palettable庫包

cmaps與palettable不是matplotlib裡的東西,所以要先conda安裝。cmaps他可以使你在matplotlib中使用NCL裡的顏色條。matplotlib中自帶的顏色條實在是比較少的,也難看。NCL中有許多經典的大氣科學繪圖配色可供使用。大牛寫個包實在是嘉惠學林。palettable也差不多,可以讓你擁有超出matplotlib的享受。這裡簡單寫個實例:

import cmaps#首先導入這個包cmap=cmaps.CBR_wet_r#CBR_wet_r#這個顏色條就不是matplotlib裡的,而是通過cmaps轉引ncl的bounds=np.arange(0,100,10)norm=mpl.colors.BoundaryNorm(bounds, cmap.N)cbar=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),cax=cax)

而且請注意,導入之後,你就可以對ncl的顏色條進行matplotlib裡的操作了,比如截取和拼接等。(你敢信第五第六節幾百個字打了兩天

七、特別的格式定製

在matplotlib中可以使用format參數對cbar的刻度的格式修改,但是有時候會有些不一樣的需求。比如下面一個色條:

上面數字格式使用的是Times New Roman,下面中文的字體是SimHei。

fc=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),             cax=ax, orientation='horizontal',extend='both')labels=fc.ax.get_xticklabels()[label.set_fontname('Times New Roman')for label in labels]

八、levels等距而colorbar刻度距離不等距

參照FuncNorm: Arbitrary function normalization這個例子,實現levels等距而cbar不等距。但是有個問題是我現在安裝的matplotlib中的源碼中,該FuncNorm類下面只有注釋,沒有內容。打開本地的matplotlib文件下的colors.py,我從頭讀到尾,確實沒有這個功能的定義。應該是開發者更新的時候出問題了,所以即便你粘貼demo過去運行也不行。

這是為了仿製前面提到的一張圖裡的cbar時涉及到的問題。可以看出,一側的標籤框線是和柱體分離的。

但是當我使用cbar.ax.spines['right'].set_position(('outward',10))來修改時,卻會只有刻度尺離開柱體的樣子。所以我嘗試第四節雙刻度列的辦法提到的新建一根坐標軸進行處理。
cmap = mpl.cm.coolnorm = mpl.colors.Normalize(vmin=5, vmax=10)fc=fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),             cax=ax, orientation='horizontal')fc.ax.tick_params(which='major',labelsize=3,direction='out',width=0.5,length=1)fc.outline.set_linewidth(0.3)ax2=fc.axax2.xaxis.set_ticks_position('top')ax2.tick_params(labelsize=3,top=True,width=0.5,length=1)ax3=ax2.secondary_xaxis('bottom')ax3.tick_params(labelsize=3,width=0.5,length=3)ax3.spines['bottom'].set_bounds(5,10)ax3.set_xticks([5,10])ax3.set_xticklabels(['0.1mm','500mm'])ax3.spines['bottom'].set_linewidth(0.3)labels=fc.ax.get_xticklabels()ax2.axis('off')fc.outline.set_color('none')ax3.spines['bottom'].set_position(('outward',10))

噹噹當,還是比較像的,後續可以通過設置label和rotation的角度來美化。不過大頭已經解決了,其他的細節我就不再贅述。(其實是打不動字了

相關焦點

  • 還在對Matplotlib繁瑣的圖層設置感到煩惱!?快來看看這個Python繪圖工具包吧
    是不是被matplotlib繁瑣繪圖屬性設置搞得一臉懵?是不是因常常記不住某一個圖層設置函數而被迫看又長又枯燥的API文檔?又或者是不是在面對多個matplotlib子圖時寫了大量的循環代碼來設置屬性?最後還是不是希望只精通一個Python繪圖包就可以把二維、空間等類型圖表繪製方法都掌握??
  • Python-matplotlib 多子圖共用colorbar
    繪製教程後,有小夥伴反應能否出一篇多子圖共用一個colorbar的系列教程,這裡也就使用自己的數據進行繪製(數據一共四列,具體為真實值和使用三個模型計算的預測值)。在繪製多子圖共用colorbar時,最重要的就是對顏色映射進行設置,這裡使用了matplotlib.color.Normalize()進行顏色和數值對應設置。先看一下使用默認設置的結果,每個子圖對應一個colorbar。
  • matplotlib繪圖的核心原理講解
    作者:朱小五來自:凹凸數據(ID:alltodata)matplotlib是基於Python語言的開源項目,旨在為Python提供一個數據繪圖包。相信大家都用過它來數據可視化,之前我還分享過25個常用Matplotlib圖的Python代碼。可是你了解過它繪圖的核心原理嗎?
  • 最全colormap和colorbar教程
    章節引言:在matplotlib和cartopy中,其常見的繪圖命令,若是帶有顏色映射的collection(s)類,則基本都可以引入cmap與colorbar功能來分析數據。cmap即是顏色映射表,colorbar即是顏色分析色條,前者只起到對繪圖對象上色的功能,後者實現色階與數值的對應。
  • Python空間繪圖-Colorbar詳解
    一、色條Colorbar的基礎在我們繪製有色階的圖片時,多會用到colorbar這個關聯利器,色條可以直接將數值與顏色連接在一起。常用的scatter、contourf是非常適合使用的。第一節我們來簡要談談常用的colorbar參數,以後例子都基於contourf命令。
  • Python可視化 | 多樣Colorbar定製化繪製技巧
    ax.tick_parmas這句話,可以參考前面的推送文章中的關於刻度軸的內容:氣象繪圖加強版(四)—坐標名、刻度、軸。通過which這個參數,我們可以將主副刻度分別設置為相反的朝向等。這裡就不在贅述。
  • Matplotlib的安裝與繪圖
    一般屬於數據的預處理和清洗完成之後,多會把數據按照橫坐標縱坐標進行繪圖,利用人工檢查數據的使用情況 Matplotlib
  • Python氣象數據處理與繪圖:Python繪圖如何自定義或使用NCL中的colormap
    提供的colormap不夠豐富,本文介紹Matplotlib的自帶色板,並介紹Python繪圖如何使用NCL中的colormap,甚至自定義色板(比如使用氣象家園調色盤生成的色板)。一、Matplotlib 自帶colormap在繪製等高線圖也就是contourf時,需要設置合適的colormap(cmap)。下面給出Matplotlib自帶的colormap。
  • Matplotlib--上帝打翻了調色板
    同樣在圖形中,我們也可以運用matplotlib工具包,繪製斑斕的圖像。此次本文將從matplotlib的繪圖樣式和色彩設置兩個方面來對圖像的形式講解,重點在於色彩的應用。Matplotlib的繪圖樣式(style)在Matplotlib中,要想設置繪製樣式,最簡單的方法是在繪製元素時單獨設置樣式。
  • matplotlib基礎繪圖命令之scatter
    在matplotlib中,scatter方法用於繪製散點圖,與plot方法不同之處在於,scatter主要用於繪製點的顏色和大小呈現梯度變化的散點圖
  • 一本書掌握Python強大的繪圖庫Matplotlib
    Python 科學可視化領域是巨大的,由無數工具組成,從最通用和最廣泛使用的工具到更專業和機密的工具。其中一些工具是基於社區的,而另一些則是由公司開發的。有些是專門為 Web 製作的,有些僅適用於桌面,有些處理 3D 和大數據,而有些則針對完美的 2D 渲染。
  • 關於matplotlib,你要的餅圖在這裡
    3.2  設置顯示顏色,Method 1:3.3  設置顯示顏色, Method 2:3.4  設置圖例(legend)3.5  重新設置圖例(legend)3.6  將某些類別突出顯示# 前言matplotlib, 官方提供的餅圖Demo,功能比較比較簡單,在實際應用過程中,往往會有許多個性化的繪製需求
  • Matplotlib二維和三維繪圖細解
    本節提要:關於m
  • python畫圖自定義colorbar
    自定義colorbar包含兩方面:這兩項比較簡單和實用,matplotlib和seaborn都可以嘗試。
  • Python Matplotlib 入門教程:如何控制Matplotlib樣式
    有時在繪圖時,您希望自定義Matplotlib圖形的顏色,希望控制Matplotlib樣式,例如,如果您在繪製線條,可以為每個線條定製顏色。()你可以看到在上面的代碼中,我們已經為我們的行指定了顏色。Matplotlib中有不同的顏色,下面是Matplotlib顏色表。
  • Python-matplotlib 繪圖配色設計
    2.1 默認圖表這裡首先設置一組數據,使用matplotlib的默認繪製方法進行圖表繪製,具體數據如下:array([10, 25, 12, 15, 28, 13, 20, 26, 23, 40, 39, 35, 42, 31, 29, 16, 27], dtype=int64)
  • Python-matplotlib: 圖表手繪風
    matplotlib.pyplot.xkcd()簡介這個Matplotlib子函數特別簡單,只有三個參數,別看參數少,但功能可不小matplotlib.pyplot.xkcd(scale=1, #相對於不使用xkcd的風格圖,褶皺的幅度
  • python使用matplotlib畫動態圖
    matplotlib是python的核心繪圖庫,是python的一個開源項目,旨在為python提供一個繪圖庫。matplotlib與numpy組合是一種可行的matlab替代方案。在可視化中matplotlib是最常使用的工具,是對數據整體判斷、效果預測不可或缺的重要模塊。下面我們就來聊一聊如何使用matplotlib繪製一個二維動態圖。
  • Matplotlib可視化菜鳥教程
    可以說是Python最聲名遠揚的可視化庫了,也是Python數據分析庫的「三駕馬車」之一。•marker:設置點的形狀;•cmap:顏色映射;•norm:當顏色c為一組浮點數時,把值標準化到[0,1]做顏色映射,vmin和vamx參數是結合 norm 來用的;
  • Python-Matplotlib: 極坐標圖形
    風玫瑰圖風玫瑰圖就是極坐標系下的堆積分組柱形圖, 這裡定義1個函數,返回繪圖對象和刻度坐標及標籤。使用時,提取刻度坐標和標籤就行了,繪圖對象使用_進行列印。ax.set_theta_offset(startangle) # 設置旋轉起點return (ax, (theta + [2*np.pi], theta_order + [None])) # 返回繪圖對象及刻度# 繪圖from matplotlib import tickerimport matplotlib.pyplot as pltplt.rcParams['font.sans-serif