【问题标题】:Matplotlib custom diverging gradient ignoring colorsMatplotlib 自定义发散渐变忽略颜色
【发布时间】:2017-08-24 17:53:04
【问题描述】:

我一直在研究一些用于 python 的数据绘图功能,我研究需要的一个这样的工具是一组差异图表,用于比较两组数据之间的变化。

我现在正处于想要绘制数据的地步,并且正在研究创建自定义颜色图来处理发散数据,但是到目前为止,我的所有绘图要么忽略渐变中的特定步骤,要么我的低值正在重复颜色。

这是生成的示例图:

我的自定义颜色图以及绘图的代码:

diffmap_17 = ["#FF0000", "#F81318", "#F12731", "#EB3B4A", "#EB5C66", "#EB7D82", "#EB9E9E", "#F1BEBE", "#F8DEDE", "#FFFFFF", "#DDDCFD", "#BCB9FB", "#9B96FA", "#6A6CFA", "#3A43FA", "#1D21FC", "#0000FF"]
diffmap_17_colormap = matplotlib.colors.ListedColormap(diffmap_17)

contour_levels = [-20, -10, -5, -2, -1, -0.75, -0.5, -0.25, -0.1, 0.0, 0.1, 0.25, 0.5, 0.75, 1, 2, 5, 10, 20]
cs = m.contourf(x,y,data,contour_levels,cmap=diffmap_17_colormap) #plot total

我的目标是让彩色地图的零点为白色,然后向外发散(红色为负,蓝色为正)。目前,我使用的是标准颜色图,但今后最好使用自定义颜色图。

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 您的数据可能不是您认为的那样。没有minimal reproducible example 很难提供帮助...
  • 我同意@Julien。从您在图片中显示的内容来看,您可能有一些难以看到的极端值,并且所有其余数据都在 -1 和 1 之间。您是否尝试过更改限制(vmin 和 @987654327 @)。此外,如果您的数据是 netcdf 等标准格式之一,那么周围有很多工具可以帮助您快速查看文件。例如,对于 netcdf 文件,我喜欢使用 ncview 预先检查我的数据。
  • 与@Thomas 和 Julien 建议的 cmets 不同,问题主要与数据无关,因为级别是明确指定的。纯粹是如何定义要使用的颜色范围的问题。我在下面的答案中显示了两个选项。然而,完整的地图是相同颜色的事实也将允许更严格的级别(范围从 -10 到 10 可能就足够了)。请注意,Julien 说在提出这样的问题时应该给出minimal reproducible example 是完全正确的(请记住下次提问)。

标签: python matplotlib colormap


【解决方案1】:

问题是颜色是通过将最小值和最大值之间的范围分成相等的部分来从颜色图中选择的。由于大多数级别彼此非常接近,因此它们属于相同的范围,因此具有相同的颜色。

最简单的解决方案是不使用颜色图,而是使用绘图,其中每个级别都从颜色列表中获取颜色。在这种情况下,您可以将颜色列表直接提供给contourf 图。

plt.contourf(x,y,data,contour_levels,colors=diffmap_17)

请注意,由于您有 19 个级别,因此您的列表将需要 18 种颜色(因此我添加了一种)。

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

x, y= np.meshgrid(np.linspace(-3,3), np.linspace(-3,3))
r = np.sqrt(x**2+y**2)
data = np.tan((r*0.7-1.5))*1.3

diffmap_17 = ["#FF0000", "#F81318", "#F12731", "#EB3B4A", "#EB5C66", "#EB7D82", 
              "#EB9E9E", "#F1BEBE", "#F8DEDE", "#FFFFFF", "#DDDCFD", "#BCB9FB", 
              "#9B96FA", "#6A6CFA", "#3A43FA", "#1D21FC", "#0000FF", "#0000ce"]

contour_levels = [-20, -10, -5, -2, -1, -0.75, -0.5, -0.25, -0.1, 0.0, 
                  0.1, 0.25, 0.5, 0.75, 1, 2, 5, 10, 20]
cs = plt.contourf(x,y,data,contour_levels,colors=diffmap_17)

plt.colorbar(cs)

plt.show()

如果您想改用颜色图,则需要与颜色图一起提供规范化实例。 matplotlib.colors.BoundaryNorm 将根据提供给它的边界列表选择颜色,这将是等高线图的级别列表。

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

x, y= np.meshgrid(np.linspace(-3,3), np.linspace(-3,3))
r = np.sqrt(x**2+y**2)
data = np.tan((r*0.7-1.5))*1.3

diffmap_17 = ["#FF0000", "#F81318", "#F12731", "#EB3B4A", "#EB5C66", "#EB7D82", 
              "#EB9E9E", "#F1BEBE", "#F8DEDE", "#FFFFFF", "#DDDCFD", "#BCB9FB", 
              "#9B96FA", "#6A6CFA", "#3A43FA", "#1D21FC", "#0000FF", "#0000ce"]
diffmap_17_colormap = matplotlib.colors.ListedColormap(diffmap_17)

contour_levels = [-20, -10, -5, -2, -1, -0.75, -0.5, -0.25, -0.1, 0.0, 
                  0.1, 0.25, 0.5, 0.75, 1, 2, 5, 10, 20]
norm = matplotlib.colors.BoundaryNorm(contour_levels, diffmap_17_colormap.N)
cs = plt.contourf(x,y,data,contour_levels,cmap=diffmap_17_colormap, norm=norm)

plt.colorbar(cs)

plt.show()

输出图同上。

【讨论】:

  • 我认为 OP 只有 17 个颜色级别的原因是因为他希望级别“以颜色为中心”,即实际轮廓级别将介于定义的级别和刻度上的刻度之间像现在这样的颜色条——这至少是我想要的。这通常很有意义,尤其是对于白电平,因为“可忽略”(接近于零)的值不会显示出趋势。也许OP可以对此发表评论......无论如何我要+1。
  • @Thomas 正确,将边界对称地放在零附近通常更有意义;但是对于那个人确实需要开始解释数据,那时我已经迷失了负降水可能有多远(可能是如果蒸发的水多于降雨量,然后显示趋势确实可能是需要)。
  • OP 显示的是差异图——两个模型使用不同的设置或可能不同的算法运行以计算降水量。在开发此类模型时,您会经常这样做。无论如何,你是对的,这完全超出了这个问题的范围。
  • 工作就像一个魅力!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 2021-02-28
  • 1970-01-01
  • 2017-07-19
  • 2019-05-14
  • 2019-08-08
  • 2019-12-07
相关资源
最近更新 更多