简体   繁体   English

xarray 离散散点 plot:指定图例/颜色顺序

[英]xarray discrete scatter plot: specifying legend/colour order

Plotting a discrete xarray DataArray variable in a Dataset with xr.plot.scatter() yields a legend in which the discrete values are ordered arbitrarily, corresponding to unpredictable colour assignment to each level.使用xr.plot.scatter()Dataset集中绘制离散xarray DataArray变量会产生一个图例,其中离散值任意排序,对应于每个级别的不可预测的颜色分配。 Would it be possible to specify a specific colour or position for a given discrete value?是否可以为给定的离散值指定特定颜色或 position?

A simple reproducible example:一个简单的可重现示例:

import xarray as xr

# get a predefined dataset
uvz = xr.tutorial.open_dataset("eraint_uvz")

# select a 2-D subset of the data
uvzr = uvz.isel(level=0, month=0, latitude=slice(150, 242),
                longitude=slice(240, 300))

# define a discrete variable based on levels of a continuous variable
uvzr['zone'] = 'A'
uvzr['zone'] = uvzr.zone.where(uvzr.u > 30, other='C')
uvzr['zone'] = uvzr.zone.where(uvzr.u > 10, other='B')

# do the plot
xr.plot.scatter(uvzr, x='longitude', y='latitude', hue='zone')

这会产生以下情节

Is there a way to ensure that the legend entries are arranged 'A', 'B', 'C' from top to bottom, say?有没有办法确保图例条目从上到下排列为“A”、“B”、“C”? Or ensure that A is assigned to blue, and B to orange, for example?或者确保 A 分配给蓝色,B 分配给橙色?

I know I can reset the values of the matplotlib color cycler, but for that to be useful I first need to know which order the discrete values will be plotted in.我知道我可以重置matplotlib颜色循环仪的值,但为了有用,我首先需要知道离散值的绘制顺序。

I'm using xarray v2022.3.0 on python 3.8.6.我在 python 3.8.6 上使用xarray v2022.3.0 With an earlier version of xarray (I think 0.16) the levels were arranged alphabetically.使用较早版本的 xarray(我认为是 0.16),级别按字母顺序排列。

I found an ugly workaround using xarray.Dataset.stack and xr.where(..., drop=True) , in case anyone else is stuck with a similar problem.我发现使用xarray.Dataset.stackxr.where(..., drop=True)的丑陋解决方法,以防其他人遇到类似问题。

import numpy as np   # for unique, to cycle through values
import matplotlib.pyplot as plt   # to get a legend

# instead of np.unique you could pass an iterable of your choice
# specifying the order
for value in np.unique(uvzr.zone):
    # convert to a 1-D dataframe with a co-ordinate including all
    # unique combinations of latitude-longitude values
    uvzr_stacked = uvzr.stack({'location':('longitude', 'latitude')})

    # now select only those grid points in zone value
    uvzr_stacked = uvzr_stacked.where(uvzr_stacked.zone == value,
                                      drop=True)

    # the plotting function can't see the original dims any more;
    # a new name is required, however
    uvzr_stacked['lat'] = uvzr_stacked.latitude
    uvzr_stacked['lon'] = uvzr_stacked.longitude

    # plot!
    xr.plot.scatter(uvzr_stacked, x='lon', y='lat', hue='zone',
                    add_guide=False)

plt.legend(title='zone')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM