首页 > 解决方案 > 如何绘制一组曲线的不确定性界限,其中每条曲线的时间步长不一致

问题描述

假设我们有一组离散点序列。每个都有不同的水平值(比如时间步长),那么在离散采样点描述的那些曲线上绘制不确定性边界的最佳方法是什么。

更具体地说,让我们定义以下两条曲线(及其离散点)

x1 = [1, 4, 5, 7, 9, 13, 20]
y1 = [0.1, 0.25, 0.22, 0.53, 0.37, 0.5, 0.55]
x2 = [2, 4, 6, 7, 9, 11, 15]
y2 = [0.03, 0.12, 0.4, 0.2, 0.18, 0.32, 0.39]
plt.plot(x1, y1)
plt.plot(x2, y2, 'red')

我们想要绘制一个带有不确定性界限和一个标准偏差的平滑均值。 在此处输入图像描述

在上图中,绿色和红色曲线是真实数据,蓝色阴影表示拟合的不确定性带。

标签: pythonmatplotlibseaborn

解决方案


如果您希望 std 在均值附近变灰,您可以通过以下方式进行。首先将数据放在一个数据框中:

import pandas as pd
import seaborn as sns

s1 = pd.Series(y1, index=x1).rename('s1')
s2 = pd.Series(y2, index=x2).rename('s2')

df = pd.concat([s1, s2], axis=1)

# Now let's unstack the dataframe so seaborn can recognize it
data = df.unstack().dropna().to_frame()
data.columns = ['values']

然后情节可以这样完成:

ax = sns.lineplot(x='level_1', y = 'values', hue='level_0',
              data=data.reset_index())

# Fill the missing points using interpolation
df_filled = df.copy().interpolate()

ma = df_filled.mean(axis=1).interpolate()

ax.plot(ma.index, ma, color='r', linestyle='--', label='mean')

mstd = ma.std()

ax.fill_between(ma.index, ma + mstd, ma - mstd,
                color='b', alpha=0.2)
plt.legend()

在此处输入图像描述

旧解决方案:昨天我发现自己遇到了类似的问题,这就是我解决它应用于您的问题的方法:

import pandas as pd
import seaborn as sns

# Convert the timeseries to pd.Serires

s1 = pd.Series(y1, index=x1).rename('s1')
s2 = pd.Series(y2, index=x2).rename('s2')

# Put all together in a dataframe

df = pd.concat([s1, s2], axis=1)

>> df
      s1    s2
1   0.10   NaN
2    NaN  0.03
4   0.25  0.12
5   0.22   NaN
6    NaN  0.40
7   0.53  0.20
9   0.37  0.18
11   NaN  0.32
13  0.50   NaN
15   NaN  0.39
20  0.55   NaN

然后使用seaborn.pointplot调整数据框,以便设置 seaborn.pointplot 的“x”、“y”变量:

data = df.unstack().dropna().to_frame()
data.columns = ['values']

>> data.reset_index()

   level_0  level_1  values
0       s1        1    0.10
1       s1        4    0.25
2       s1        5    0.22
3       s1        7    0.53
4       s1        9    0.37
5       s1       13    0.50
6       s1       20    0.55
7       s2        2    0.03
8       s2        4    0.12
9       s2        6    0.40
10      s2        7    0.20
11      s2        9    0.18
12      s2       11    0.32
13      s2       15    0.39

最后,如果绘图的结果是这样的:

ax = sns.pointplot(x='level_1', y = 'values', ci='sd',
                   data=data.reset_index())

ax.set_xlabel('')

在此处输入图像描述

中间点应该是该时间点的平均值,误差条默认调整为“sd”(您可以将“ci”中的置信区间也设置为浮点数或删除它。更多信息在文档)。


推荐阅读