如何让蒙版数组为pyplot中的整个段着色?

Posted

技术标签:

【中文标题】如何让蒙版数组为pyplot中的整个段着色?【英文标题】:How to get masked array to color whole segment in pyplot? 【发布时间】:2020-12-09 03:51:44 【问题描述】:

当我的 y 值超过阈值(在本例中为 30)时,我一直希望我的时间序列变为红色。

我浏览并找到了this article,它给出了两个主要建议:使用掩码数组或按段构建颜色图。当我尝试重新设计颜色映射解决方案时,我返回一个关键错误 [0],但是当我尝试使用屏蔽数组时,我得到以下信息:

这非常接近我的需要,但我似乎无法找到一种方法来为阈值以上的整条线着色,而只是对部分进行着色。如何让整条线在阈值线上方显示为红色?

这是我用来生成情节的代码:

#Note: This isn't my source data, but will show the same effect
ut9_ffwi = [2, 15, 14, 28, 40, 49, 27, 36, 24, 12]
ut9_time = range(0, 10, 1)

threshold = 30
ut9_ffwi = np.ma.array(ut9_ffwi)
ut201_ffwi = np.ma.array(ut201_ffwi)
mask = ma.masked_where(ut9_ffwi <= threshold, ut9_ffwi)

# Plot
plt.plot(ut9_time, ut9_ffwi)
# Highlight values above 30
plt.plot(ut9_time, mask, 'r', linewidth=3.2)
# Plot a horizontal line for threshold
plt.axhline(y = threshold, color='r', linestyle='-')
plt.xticks(rotation = 90)
plt.legend(['FFWI Data', 'Threshold'])

【问题讨论】:

问题是它正在检测高于 30 的数据值并将它们之间的线更改为红色,您需要某种插值来生成线穿过 30 的新点以获得良好的连续性红色的。不知道如何发布答案,但认为这可能会有所帮助:) 【参考方案1】:

您可以按照Multicolored Line 的指南进行操作。 cmets 中指出的技巧是使用非常精细的网格进行插值,这样您就可以将段停止在相对靠近您的截止点的位置。此处的示例使用了您的变量,但为了真正说明这一点有点吵。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap, BoundaryNorm

np.random.seed(410112)
ut9_ffwi = np.random.randint(0, 50, 100)
ut9_time = range(len(ut9_ffwi))

# Interpolate using a very fine grid
Nfine = 500
x = np.linspace(ut9_time[0], ut9_time[-1], len(ut9_time)*Nfine)
y = np.interp(x, ut9_time, ut9_ffwi)

# Now to color the segments
cmap = ListedColormap(['b', 'r'])
norm = BoundaryNorm([0, 30, np.inf], cmap.N)

points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(y)
lc.set_linewidth(3)
plt.gca().add_collection(lc)

plt.xlim(x.min(), x.max())
plt.ylim(y.min(), y.max())

plt.show()


如果您设置Nfine=1,那么它会像没有插值一样绘制到更精细的网格,并且您会看到线段溢出边界。 Nfine 越大,噪声数据的边界就越清晰,尽管代价是绘制了很多点。

【讨论】:

当我遵循您的解决方案时,我在 x 声明中得到一个关键错误 0,当我将其更改为 1 时,我在 -1 索引上得到相同的错误。我会阅读源文档,但如果您对我为什么会收到该错误有任何提示,请告诉我 @SammyWammy 使用您的真实数据,您可能有日期时间,这会使获取正确的 x 变得复杂。至少您可以切换到.iloc 以确保您获得第一个值,例如ut9_time.iloc[0], ut9_time.iloc[-1] 是的,这是导致该问题的原因,因为我的数据实际上是日期时间(尽管您指出,否则似乎没有必要)。唯一剩下的问题是现在我抱怨数据类型“ufunc'multiply'不包含签名匹配类型的循环(dtype(' dtype(' @SammyWammy 如果您使用时间的整数表示 x = np.linspace(ut9_time[0].value, ut9_time[-1].value, len(ut9_time)*Nfine) 它应该可以工作,但是您需要一种方法来修复它绘制的值的表示。

以上是关于如何让蒙版数组为pyplot中的整个段着色?的主要内容,如果未能解决你的问题,请参考以下文章

为 UIBezierPath 着色

OpenGlES:如何加载着色器代码

如何将矩阵数组更新为 glsl 着色器

为 MFC 静态标签的整个背景着色

在 OpenCV 中应用蒙版

backgroundTint 属性为整个 TextInputEditText 着色