python -- 如何实现colorbar的不等间距显示

python --如何实现colorbar的不等间距显示

先展示一下结果:
在这里插入图片描述
实现上述colorbar,主要使用一个函数,如下:

  • matplotlib.colors.TwoSlopeNorm
    函数说明:
  • 一般包含三个参数:matplotlib.colors.TwoSlopeNorm(vcenter, vmin=None, vmax=None)
    • vmin:最小范围
    • vmax:最大范围
    • vcenter:中间范围

功能说明:

  • 使用一个固定中心的标准化数据。当在概念中心周围映射变化速率不等的数据时很有用,例如,数据范围从 -20到40,中点为0。

代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Dec  7 10:12:20 2022

@author: jianpu

@blog :  https://blog.csdn.net/weixin_44237337?spm=1000.2115.3001.5343

@email: 211311040008@hhu.edu.cn

introduction : keep learning althongh walk slowly
"""

import cmaps
from matplotlib.colors import ListedColormap 
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl  
import matplotlib.cm as cm
import matplotlib.colors as mcolors
newcmap=(plt.get_cmap('RdBu_r')) 
bins = np.array( [-20,-10,0,10,20,30,40])
fig=plt.figure(figsize=(10,10),dpi=150)
norm = mcolors.TwoSlopeNorm(vmin=-20, vcenter=0,vmax=40) 
ax=fig.add_axes([0,0,0.5,0.05])  
fc1=fig.colorbar(
    mpl.cm.ScalarMappable(norm=norm,cmap=newcmap,),   
                 cax=ax,       
                  ticks = bins,                                               
                 orientation='horizontal',                          
                 )      
##### 设置colorbar label的不同显示位置
ax2=fc1.ax
ax2.xaxis.set_ticks_position('top')  #将数值刻度移动到上边
ax3=ax2.secondary_xaxis('bottom')    #新建ax3,使ax3与ax2完全相同,但是是处于下部
ax3.set_xticks([-10,0,10,20,30])
# 这里的标签名称可以自定义修改成想要的
ax3.set_xticklabels(['a','b','c','d','e'],ha="center") 
# f1.ax.set_xscale('linear')

举例示范2:

  • 有时我们希望在概念中心点的两侧有不同的颜色映射,我们希望这两种颜色映射具有不同的线性比例。例如,在地形图中,陆地和海洋的中心位于零,但陆地的海拔高度范围通常比水的深度范围大,而且它们通常由不同的颜色图表示。
    在这里插入图片描述

代码如下:

"""
Created on Wed Dec  7 10:12:20 2022

@author: jianpu

@blog :  https://blog.csdn.net/weixin_44237337?spm=1000.2115.3001.5343

@email: 211311040008@hhu.edu.cn

introduction : keep learning althongh walk slowly
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cbook as cbook
from matplotlib import cm
dem = cbook.get_sample_data('topobathy.npz', np_load=True)
topo = dem['topo']
longitude = dem['longitude']
latitude = dem['latitude']

fig, ax = plt.subplots(dpi=200)
# make a colormap that has land and ocean clearly delineated and of the
# same length (256 + 256)
colors_undersea = plt.cm.terrain(np.linspace(0, 0.17, 256))
colors_land = plt.cm.terrain(np.linspace(0.25, 1, 256))
all_colors = np.vstack((colors_undersea, colors_land))
terrain_map = colors.LinearSegmentedColormap.from_list(
    'terrain_map', all_colors)

# make the norm:  Note the center is offset so that the land has more
# dynamic range:
divnorm = colors.TwoSlopeNorm(vmin=-500., vcenter=0, vmax=4000)

pcm = ax.pcolormesh(longitude, latitude, topo, rasterized=True, norm=divnorm,
                    cmap=terrain_map, shading='auto')
# Simple geographic plot, set aspect ratio because distance between lines of
# longitude depends on latitude.
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
ax.set_title('TwoSlopeNorm(x)')
cb = fig.colorbar(pcm, shrink=0.9)
cb.set_ticks([-500, 0, 1000, 2000, 3000, 4000])
plt.show()

举例示范3:
在这里插入图片描述
这一种适用于通过不同的rgb色域,拼接得到的colormap,使用的主要函数为:

  • matplotlib.colors.BoundaryNorm(boundaries, ncolors, clip=False, *, extend='neither')

  • 官网说明

  • 主要用来生成基于离散区间的颜色图索引

  • 与Normalize或LogNorm不同,BoundaryNorm将值映射为整数,而不是0-1的区间。

    • boundaries:至少2个 bin 边的单调递增序列: 第 n 个 bin 中的数据将被映射到第 n 个颜色。
    • ncolors:要使用的颜色图中的颜色数。
    • clip:如果为 True,则超出范围的值如果低于边界[0]则映射为0,如果高于边界[ -1]则映射为 ncolor-1。如果为 False,超出范围的值如果低于边界[0]则映射为 -1,如果高于边界[ -1]则映射为 ncolor。然后,这些索引通过 Colormap 转换为有效的索引。
# -*- coding: utf-8 -*-
"""
Created on Wed Dec  7 10:12:20 2022

@author: jianpu

@blog :  https://blog.csdn.net/weixin_44237337?spm=1000.2115.3001.5343

@email: 211311040008@hhu.edu.cn

introduction : keep learning althongh walk slowly
"""

import cmaps
from matplotlib.colors import ListedColormap 
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl  
import matplotlib.cm as cm
import matplotlib.colors as mcolors
rgb=(
     [0,0,255],
     [39,39,255],
     [78,78,255],
     [91,118,255],
     [118,130,255],
     
     [ 255,255,255],
     [ 255,255,255],
     
     [ 255,190,190],
     [ 255,142,142],
     [ 255,122,122],
     [ 255,99,99],
     [ 255,58,58],
     [ 248,19,8],
     [ 153,33,20],
     )
rgb=np.array(rgb)/255.0
newcmap=ListedColormap(rgb) 
bins = [-600,-500,-400,-300,-200,-100,0,100,200,300,400,500,600,800,1000]
nbin = len(bins) - 1
cmap = cm.get_cmap('bwr', nbin)
norm4 = mcolors.BoundaryNorm(bins, nbin)
im4 = cm.ScalarMappable(norm=norm4, cmap=newcmap)

fig=plt.figure(figsize=(10,10),dpi=150)

ax=fig.add_axes([0,0,0.5,0.05])  
f1 = fig.colorbar(
    im4, cax=ax, orientation='horizontal',
   
)    



举例示范4:
在这里插入图片描述

这里所使用的是对数colorbar显示,最重要的原则是保持线条图和 ScalarMapable 的颜色同步。这意味着,线条的颜色不应取自独立的颜色列表,而应取自相同的颜色图,并使用与要显示的颜色条相同的标准化。然后,一个主要问题是决定如何处理不能成为对数规范化的一部分的0。下面是使用 SymLogNorm 假设0到2之间的线性范围和上面的日志范围的解决方案。

代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Feb  6 21:24:46 2023

@author: win10
"""

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

"""Creating the data"""
time_vector = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
amplitudes = [t ** 2 * np.exp(-t * np.power(np.linspace(-0.5, 0.5, 100), 2)) for t in time_vector]

"""Getting the non-zero minimum of the data"""
data = np.concatenate(amplitudes).ravel()
data_min = np.min(data[np.nonzero(data)])

"""Creating K-space data"""
k_vector = np.linspace(0,1,100)

"""Plotting"""
cmap = plt.cm.get_cmap("jet")
norm = mpl.colors.SymLogNorm(2, vmin=time_vector[0], vmax=time_vector[-1])

sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])
fig =plt.figure(dpi=200)
for i in range(len(time_vector)):
    plt.plot(k_vector, amplitudes[i], color=cmap(norm(time_vector[i])), label=time_vector[i])

#c = np.arange(1, number_of_plots + 1)
plt.xlabel('Frequency')
plt.ylabel('Amplitude')
plt.yscale('symlog')
plt.xscale('log')
plt.legend(loc=3)

cbar = plt.colorbar(sm, ticks=time_vector, format=mpl.ticker.ScalarFormatter(), 
                    shrink=1.0, fraction=0.1, pad=0)

plt.show()

单独的一个记录5:

  • 这个只是记录如何将colorbar的标签放在每个色标的中间的另一种方法
  • 之前尝试过别的方法,具体教程在这里:点击这里
    在这里插入图片描述
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1., n_lines + 1)

cmap = plt.get_cmap("jet", len(c))
norm = matplotlib.colors.BoundaryNorm(np.arange(len(c)+1)+0.5,len(c))
sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])  # this line may be ommitted for matplotlib >= 3.1

fig, ax = plt.subplots(dpi=200)
for i, yi in enumerate(y.T):
    ax.plot(x, yi, c=cmap(i))
fig.colorbar(sm, ticks=c)
plt.show()

参考如下:

  • https://matplotlib.org/stable/tutorials/colors/colormapnorms.html#twoslopenorm-different-mapping-on-either-side-of-a-center
  • https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.TwoSlopeNorm.html
  • https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.BoundaryNorm.html
  • https://zhajiman.github.io/post/matplotlib_colormap/
  • https://stackoverflow.com/questions/54513247/matplotilb-how-to-set-colorbar-for-line-plot-with-log-scale
  • https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/49374315#49374315
  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简朴-ocean

继续进步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值