Python 当值间距不均匀时,在matplotlib中打印分类数据

Python 当值间距不均匀时,在matplotlib中打印分类数据,python,matplotlib,python-xarray,Python,Matplotlib,Python Xarray,我需要创建一个具有不均匀间距值的网格数据的二维图像。我正在绘制一个分类数据集,其中类别使用对应于特定标签的数值进行编码 我需要能够使用格式化程序为数据集中的每个类别分配不同的颜色。这最好是灵活的,因为我正在绘制的真实数据集有30个独特的类别。因此,当值为10和40时,我应该有一个唯一的颜色 制作示例数据进行演示 将xarray作为xr导入 将matplotlib.pyplot作为plt导入 将numpy作为np导入 作为pd进口熊猫 时间=pd.日期范围('2010-01-31','2015-1

我需要创建一个具有不均匀间距值的网格数据的二维图像。我正在绘制一个分类数据集,其中类别使用对应于特定标签的数值进行编码

我需要能够使用格式化程序为数据集中的每个类别分配不同的颜色。这最好是灵活的,因为我正在绘制的真实数据集有30个独特的类别。因此,当值为
10
40
时,我应该有一个唯一的颜色

制作示例数据进行演示

将xarray作为xr导入
将matplotlib.pyplot作为plt导入
将numpy作为np导入
作为pd进口熊猫
时间=pd.日期范围('2010-01-31','2015-12-31',频率=M')
lat=np.linspace(0,1224)
lon=np.linspace(0,1176)
有效值=[10,40,50,60]
标签=['type_1'、'type_2'、'type_3'、'type_4']
lookup=dict(zip(有效值、标签))
value=np.random.choice(有效值,大小=(len(时间),len(纬度),len(经度)))
rand_nans=np.random.random(大小=(len(时间)、len(纬度)、len(经度))<0.3
值[rand_nans]=np.nan
coords={'time':time'lat':lat'lon':lon}
dims=[“时间”、“纬度”、“经度”]
ds=xr.Dataset({'lc_code':(dims,values)},coords=coords)
#转换为numpy数组(仅第一个时间步)
im=ds.isel(时间=0).lc\u代码值
ds
出[]:
尺寸:(纬度:224,经度:176,时间:72)
协调:
*时间日期时间64[ns]2010-01-31 2010-02-28。。。2015-12-31
*lat(lat)浮动64 0.0 0 0.004484 0.008969 0.01345。。。0.991 0.9955 1.0
*lon(lon)浮动64 0.0 0 0.005714 0.01143 0.01714。。。0.9886 0.9943 1.0
数据变量:
lc_代码(时间、纬度、经度)浮动64 50.0 nan 60.0 50.0。。。40.0 10.0 40.0 10.0
仅绘制图像数据就有两个问题: 1) 勾号标签不是
labels
2) 颜色栏的间距均匀,但值不均匀。这样我们就有了
10,40,50,60的值

plt.imshow(im,cmap=plt.cm.get\u cmap('tab10',len(有效值)))
plt.colorbar()

因此,我尝试了
函数格式化程序
。但是,此图像仍然存在一个问题,即没有值映射到
type_2
颜色,尽管勾号标签排列在颜色栏的中心

fig,ax=plt.子批次(figsize=(12,8))
plt.imshow(im,cmap=plt.cm.get\u cmap('tab10',len(有效值)))
#计算记号标签的位置
最小值=最小值(有效值)
最大值=最大值(有效值)
位置=np.linspace(最小值、最大值、长度(有效值))
val_lookup=dict(zip(位置、标签))
def格式化程序功能(x,位置):
'两个参数是值和记号位置'
val=val_查找[x]
返回值
格式化程序=plt.FuncFormatter(格式化程序_func)
#我们必须确保指定与目标名称匹配的记号
plt.colorbar(刻度=位置,格式=格式化程序,间距=比例);
#设置颜色栏限制,使标记均匀分布
plt.clim(0,70)

但此代码强制第二类(值
40
type_2
)不显示为与
勾号对齐的颜色。因此,颜色栏不能有效地反映图像中的数据

(im==40).mean()
出[]:
0.17347301136363635

在第一个绘图中,没有颜色映射到类型2颜色的原因是23和35之间没有值,这大致是分配给红色的范围

您可以尝试使用
ListedColormap

将xarray作为xr导入
将matplotlib.pyplot作为plt导入
从matplotlib导入颜色
将numpy作为np导入
作为pd进口熊猫
时间=pd.日期范围('2010-01-31','2015-12-31',频率=M')
lat=np.linspace(0,1224)
lon=np.linspace(0,1176)
有效_值=[10,40,50,60]
标签=['type_1'、'type_2'、'type_3'、'type_4']
lookup=dict(zip(有效值、标签))
values=np.random.choice(有效的_值,大小=(len(time),len(lat),len(lon)))
rand_nans=np.random.random(大小=(len(时间)、len(纬度)、len(经度))<0.3
值[rand_nans]=np.nan
coords={'time':time'lat':lat'lon':lon}
dims=[“时间”、“纬度”、“经度”]
ds=xr.Dataset({'lc_code':(dims,values)},coords=coords)
#转换为numpy数组(仅第一个时间步)
im=ds.isel(时间=0).lc\u代码值
#构建一个列出的颜色映射。
c_map=colors.ListedColormap(['白色'、'红色'、'蓝色'、'绿色']))
界限=[-15,35,45,55,65]
norm=colors.BoundaryNorm(bounds,c_map.N)
#用颜色条打印图像
im=plt.imshow(im,cmap=c_图,norm=norm)
c_条=plt.colorbar(
im,cmap=c_映射,norm=norm,boundary=bounds,ticks=[10,40,50,60])
c_bar.ax.set_xticklabel(['type_1'、'type_2'、'type_3'、'type_4']))
plt.show()
这将提供以下输出:

为了使标签位于颜色条区域的中心,您只需确保勾号值(在
plt.colorbar
参数中)正好位于相关
边界的中间。我硬编码这些,但你可以很容易地计算这些自动!我认为边界的间距不相等并不重要,因为
ListedColormap
是隐式分类的,因此它理解为使每个类别的颜色栏大小相等

希望这有帮助