如何绘制一组曲线的不确定性边界,其中每条曲线的时间步长不一致

时间:2018-09-12 14:25:07

标签: python matplotlib seaborn

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

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

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')

我们想要绘制具有一个标准偏差的不确定范围的平滑均值。 enter image description here

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

1 个答案:

答案 0 :(得分:2)

如果您希望平均值周围的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()

enter image description here

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

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('')

enter image description here

中间点应该是该时间点的平均值,并且默认情况下将误差线调整为“ sd”(您可以将“ ci”中的置信区间也设置为浮点数,也可以将其删除。) documentation中的信息)。