爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 6736|回复: 4

[源代码] *笨办法实现等值线图【非线性配色】和【两头开色条】

[复制链接]

新浪微博达人勋

发表于 2022-6-26 12:16:58 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 15195775117 于 2022-6-26 12:47 编辑

1、需求缘起

用matplotlib画【填色等值线图】,有plt.contourf和plt.tricontourf两个函数,画的图如下:
默认色条.png

这里有2个问题:
1、默认的色条,刻度值都是均匀的,
   但工作中经常遇到需要对数据进行【非线性配色】的情况,
   例如对湿度配色的值是[5,10,20,40,80,95](%)
2、默认的色条,两端是将刻度顶到头的,
   但工作中,两头超出范围的值是额外配色的,
   例如低于最低值的都配白色,高于最高值的都配紫色。
这种姑且称为“两头开”色条。

以下,用一套笨办法解决这2个问题。


2、非线性配色,与“两头开”色条

处理效果图:
色条刻度是非线性的,且“两头开”

非线性配色.png

源代码:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap

# ======准备阶段,准备些必要的数据======

# 我们准备一个颜色序列,用于配色,
# 注意,颜色的写法比较灵活,支持3种
rgblist=[[0.5,0.5,0.5], # 灰色
        "#0000ff",      # 蓝色
        "#00ffff",      # 青色
        "#00ff00",      # 绿色
        "#ffff00",      # 黄色
        (1,0,0),        # 红色
        "#000000"       # 黑色


# 画等值线的层级,设置为不均匀的:
level=[5,6,8,11,15,20]

# “两头开”的色条,等值线层级有6个,颜色有7个,颜色比层级多1个

# 准备需要配色的数组:
data=np.random.randint(1,25,(8,10))
lng=np.linspace(100,120,10)
lat=np.linspace(20,30,8)


# ======至此,材料准备好了,以下开始画图======

# 将data转为浮点型数组,不然后续对data元素的修改都只能是整型,会出错
data=np.array(data,dtype=np.float32)

# 将颜色序列转为色条对象,可以直接由contourf函数引用
cmap = ListedColormap(rgblist)

# 配色层级数:
nlevel=len(level)

# 用data2代替data进行配色
data2=data

# 找出每个层级的元素的位置,追加到plist中:
plist=[]

# 低于最低层级的元素:
p=np.where(data2<level[0])
plist.append(p)

# 中间层级的元素:
for i in range(nlevel-1):
    p=np.where((data2>=level)&(data2<level[i+1]))
    plist.append(p)

# 高于最高层级的元素:
p=np.where(data2>=level[-1])
plist.append(p)

# 将每个层级的元素,以其所在层级序数替换之,这就实现了层级的线性
for i in range(nlevel+1):
    data2[plist]=i+0.5

# 画data2:
plt.contourf(lng,lat,data2,range(nlevel+2),cmap=cmap)

# 色条的标题和小数位数
cb=plt.colorbar(label='nonlinear',format='%.1f')

# 伪装色条的刻度:
cb.set_ticks(ticks=np.arange(nlevel)+1,labels=level)

plt.show()




密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2022-6-26 14:54:08 | 显示全部楼层
matplotlib.colors模块里的BoundaryNorm能直接实现这一功能,可见
http://bbs.06climate.com/forum.php?mod=viewthread&tid=100123
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2022-6-26 18:33:24 | 显示全部楼层
灭火器 发表于 2022-6-26 14:54
matplotlib.colors模块里的BoundaryNorm能直接实现这一功能,可见
http://bbs.06climate.com/forum.php?mo ...

{:5_245:}{:5_245:}
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2022-7-1 10:34:21 | 显示全部楼层
谢谢分享!!!!!!!!!!!!
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2022-7-3 17:13:48 | 显示全部楼层
画图解决不了的就解决数据,把原来非线性分布的数据,处理为按色标值分别的数据,比如红色对应1,蓝色对应2,依次这样,应该就可以出想要的效果了
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表