在Matplotlib的线图中绘制带阴影的不确定区域,当数据包含NaN时

27

我希望得到一个看起来像这样的图表: plot with uncertainty

我正在尝试使用matplotlib完成这个图表:

fig, ax = plt.subplots()

with sns.axes_style("darkgrid"):
    for i in range(5):
        ax.plot(means.ix[i][list(range(3,104))], label=means.ix[i]["label"])
        ax.fill_between(means.ix[i][list(range(3,104))]-stds.ix[i][list(range(3,104))], means.ix[i][list(range(3,104))]+stds.ix[i][list(range(3,104))])
    ax.legend()

我希望阴影区域的颜色与中心线相同。但现在我的问题是,means 中有一些 NaN,而 fill_between 不接受它。我收到了以下错误:

TypeError: 没有为输入类型支持 ufunc 'isfinite',也无法根据强制转换规则“安全”将输入安全地强制转换为任何支持的类型

你有什么想法来实现我的目标吗?解决方案不必使用 Matplotlib,只要能为多个系列绘制带有其不确定性的点即可。

2个回答

36

好的,问题之一是我的数据的 dtypeobject 而不是 float,这导致当 fill_between 查看数字是否有限时失败。最终我通过 (a) 转换为 float,然后 (b) 使用颜色板来解决不确定性和线条匹配颜色的问题。所以我现在有:

import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
fig, ax = plt.subplots()
clrs = sns.color_palette("husl", 5)
with sns.axes_style("darkgrid"):
    epochs = list(range(101))
    for i in range(5):
        meanst = np.array(means.ix[i].values[3:-1], dtype=np.float64)
        sdt = np.array(stds.ix[i].values[3:-1], dtype=np.float64)
        ax.plot(epochs, meanst, label=means.ix[i]["label"], c=clrs[i])
        ax.fill_between(epochs, meanst-sdt, meanst+sdt ,alpha=0.3, facecolor=clrs[i])
    ax.legend()
    ax.set_yscale('log')

这让我得到了以下结果: 在此输入图片描述


非常好的答案,它解决了问题,而不需要使用seaborn的时间序列...谢谢! - David Alvarez
1
如果您没有安装seaborn,可以使用pyplot.fill_between;调用方式类似。 - Yibo Yang

3
你可以直接从你的means DataFrame中删除NaNs并绘制生成的DataFrame?在下面的示例中,我试图接近你的结构,我有一个带有一些NaN的means DataFrame。我想stds DataFrame可能在相同的位置上也有NaN,但在这种情况下并不重要,我从means中删除NaN以得到temp_means,然后使用temp_means中剩余的索引从stds中提取标准差值。这些图展示了在删除NaN之前(顶部)和之后(底部)的结果。
x = np.linspace(0, 30, 100)
y = np.sin(x/6*np.pi)
error = 0.2

means = pd.DataFrame(np.array([x,y]).T,columns=['time','mean'])
stds = pd.DataFrame(np.zeros(y.shape)+error)

#sprinkle some NaN in the mean
sprinkles = means.sample(10).index
means.loc[sprinkles] = np.NaN


fig, axs = plt.subplots(2,1)

axs[0].plot(means.ix[:,0], means.ix[:,1])
axs[0].fill_between(means.ix[:,0], means.ix[:,1]-stds.ix[:,0], means.ix[:,1]+stds.ix[:,0])

temp_means = means.dropna()

axs[1].plot(temp_means.ix[:,0], temp_means.ix[:,1])
axs[1].fill_between(temp_means.ix[:,0], temp_means.ix[:,1]-stds.loc[temp_means.index,0], temp_means.ix[:,1]+stds.loc[temp_means.index,0])


plt.show()

enter image description here


谢谢!我会尝试这个。 - patapouf_ai
好的,我的问题是另外一件事。我的数据类型是对象而不是浮点数类型,这就是为什么当fill_between尝试使用np.isfinite时会出现值错误。现在我已经解决了这个问题。但问题是现在所有的曲线都有相同的阴影颜色。我该如何做到让中间线和其不确定性具有相同的颜色? - patapouf_ai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接