在应用对数轴缩放后,Seaborn线图中的负误差条界限如何变换?

-2 投票
1 回答
37 浏览
提问于 2025-04-11 22:00

我正在用Seaborn画一些线条:


import matplotlib.pyplot as plt 
import seaborn as sns
import pandas as pd

# dfs: dict[str, DataFrame]

fig, ax = plt.subplots()

for label, df in dfs.items():
    sns.lineplot(
        data=df,
        x="Iteration",
        y="Loss",
        errorbar="sd",
        label=label,
        ax=ax,
    )

ax.set(xscale='log', yscale='log')

结果看起来像这样

注意到“effector_final_velocity”曲线下方的误差带中有一些被截断的负值,因为在那些迭代中,损失的标准差比它的平均值要大。

不过,如果在循环调用sns.lineplot之前调用了ax.set(xscale='log', yscale='log'),结果就会变成这样

我不太确定这些未被截断的值是怎么产生的。

查看seaborn.relational的源代码:在lineplot的最后,会调用一个_LinePlotter实例的plot方法。它通过将已经计算好的标准差范围传递给ax.fill_between来绘制误差带。

在这些范围的值被传递给ax.fill_between之前检查,发现负值(本该被截断的)仍然存在。因此我认为“未截断”的行为可能是matplotlib在调用ax.fill_between时做的,因为_LinePlotter.plot在返回之前似乎没有对任何数据进行其他相关的后处理,而lineplot也立即返回。

不过,考虑一个小例子,调用fill_between时一些下限是负数:

import numpy as np 

fig, ax = plt.subplots(1, 1, figsize=(5, 5))

np.random.seed(5678)

ax.fill_between(
    np.arange(10), 
    np.random.random((10,)) - 0.2,
    np.random.random((10,)) + 0.75,
)

ax.set_yscale('log')

那么无论是在ax.fill_between之前还是之后调用ax.set_yscale('log'),结果都没有区别,都是这样

我花了一些时间在Seaborn和matplotlib的文档中寻找答案,也在Stack Overflow和其他地方查找,但没有找到关于这里发生了什么的任何信息。

1 个回答

暂无回答

撰写回答