首页 > 解决方案 > 用 Seaborn 绘制多个实验记录的统计信息

问题描述

我有一个随机算法,我重复了几次,所以我可以对其进行统计评估。可以对来自实验的数据框进行分组以计算平均值和中位数。

现在,我想用 Seaborn 绘制原始信息以及我还计算出的统计数据。所以我有多达 100 个数据框,其中包含这样的数据。

module, coverage, timestamp
examples.monkey, 32.142857142857146, 1546513589.59586
examples.monkey, 35.714285714285715, 1546513589.609822
examples.monkey, 35.714285714285715, 1546513589.617172
...
util.container, 27.586206896551722 ,1546513594.559889
util.container, 27.586206896551722 ,1546513594.579989
util.container, 27.586206896551722 ,1546513594.598491

我可以简单地用线图打印多个时间序列,如下所示。

sns.set(style="darkgrid")
for df in dfs:
    min_timestamp = df['timestamp'].min()
    df["time"] = df["timestamp"] - min_timestamp

keys = ["Run " + str(i) for i in range(len(dfs))]
glued = pd.concat(dfs, keys=keys).reset_index(level=0).rename(columns={'level_0': 'run'})
ax = sns.lineplot(hue="module", x="time", y="coverage", ci="sd", units="run", estimator=None, data=glued)
plt.show()

这导致了这样的情节:不同算法运行的绘图

然后我可以计算平均值并将其添加到图中,如下所示:

sns.set(style="darkgrid")
for df in dfs:
    min_timestamp = df['timestamp'].min()
    df["time"] = df["timestamp"] - min_timestamp

keys = ["Run " + str(i) for i in range(len(dfs))]
glued = pd.concat(dfs, keys=keys).reset_index(level=0).rename(columns={'level_0': 'Run'})
sns.lineplot(hue="module", x="time", y="coverage", ci="sd", units="Run", estimator=None, data=glued)

means = glued.groupby(by=["module", "time"], as_index=False).mean()
means["run"] = "Mean"
sns.lineplot(hue="module", x="time", y="coverage", estimator="mean", palette=sns.xkcd_palette(["red", "black"]),  err_style="band", data=means)

plt.show()

然而,由此产生的情节是相当无用的。它看起来像这样。

来自不同算法的绘图以均值运行

我更愿意对 seaborn 的例子感兴趣,我的测量值被打印为一个区域,平均值清晰可见。Seaborn 示例

现在我怀疑,我得到了这个丑陋的图像,因为具有平均值的数据帧有更多的数据点。该算法以随机间隔进行测量,因此时间戳大部分时间不会重叠。由于测量值非常接近,并且在它们之间画了一条线,我们得到了这个大笔画的图片。

我现在的具体问题是,线图在这里是否有意义,如果它是正确的方法,我自己事先计算平均值?如果方法是正确的,我该如何解决它,如果不是,您还使用什么?

我还在这里上传了一些示例结果作为 csv 文件,以防您想尝试:1 2 3 4 5

标签: pythonpandasplotseaborn

解决方案


我不确定您lineplot在第二个示例中是否正确使用。重点是让 seaborn 计算统计数据并为您绘制图形估计器 ± ci。我没有看到计算数据帧中的平均值,然后要求 seaborn 绘制数据帧的平均值的意义。

但无论如何,您的问题是 seaborn 只聚合具有完全相同 x 值的 y 值。从文档中

默认情况下,该图在每个 x 值处聚合多个 y 值,并显示集中趋势的估计值和该估计值的置信区间。

正如您正确猜测的那样,您的值太随机且很少重叠,这意味着 seaborn 无法计算出有意义的平均值。在我看来,解决方案是降低测量的时间分辨率,以便在(比方说)0.1 个时间单位期间进行的所有测量具有相同的时间值,这将使 seaborn 将它们平均在一起。

glued["roundtime"] = glued["time"].round(1)  # 1 significant digit
ax = sns.lineplot(hue="module", x="roundtime", y="coverage", ci="sd", estimator='mean', data=glued)

在此处输入图像描述


推荐阅读