Seaborn distplot 在对数刻度下添加注释会产生错误。

6
%matplotlib inline
import seaborn as sns
titanic = sns.load_dataset('titanic')
ax1 = sns.distplot(titanic['fare'], kde=False, bins=15,)

# ax1.set_yscale('log')

for p in ax1.patches:
    ax1.annotate(
        s=f"{p.get_height():1.0f}",
        xy=(p.get_x() + p.get_width() / 2., p.get_height()), 
        xycoords='data',
        ha='center', 
        va='center', 
        fontsize=11, 
        color='black',
        xytext=(0,7), 
        textcoords='offset points',
    )

以上代码绘制了泰坦尼克号数据集中Fare的直方图,其中每个条形图都使用ax1.annotate注释其值。问题在于当我想将y轴比例设置为对数刻度时--取消set_yscale行的注释并运行它,它会抛出一个错误,如下所示:

ValueError: 378x84035像素的图像大小太大了。每个方向上必须小于2^16。

也许应该更改xycoords参数,但我不太确定要更改为什么。
我使用的是Python 3.7.2,seaborn版本0.9.0。Matplotlib版本3.0.2,并且我正在使用Inline后端。

是的,我使用了对数刻度,注释也位于柱形图顶部。我正在使用具有内联显示功能的JuPyter笔记本。 - Sheldore
@ImportanceOfBeingErnest 版本3.0.2,后端是 "'module://ipykernel.pylab.backend_inline'"。 - Troy
1
使用Ann.set_inlayout(False)将注释从布局中移除?Inline使用bbox_inches = tight可能会在元素绘制出轴时导致问题。 - Jody Klymak
1
@JodyKlymak 用这个方法解决了,但是应该是 ann = ax1.annotate(...); ann.set_in_layout(False)。如果你写出一个答案,我会接受的。 - Troy
1
我认为y=0处的散点自动排除并且不会被绘制。因此,收集的范围不包括该点,因此不应该引起任何问题。(尽管在对数刻度上的散点自动缩放可能仍会存在问题。)注释需要以不同的方式处理,因为通常您希望它们在轴外部。但是如上所述,我认为“clip”属性(或者因而是“visible”属性)是是否在布局中包含它们的最佳指示。代码中似乎缺少这部分。 - ImportanceOfBeingErnest
显示剩余10条评论
1个回答

6
一些注释被放置在y=0。这将导致在对数刻度上位置未定义。
在具有内联后端的jupyter笔记本中,显示图形的默认选项是通过savefigbbox_inches="tight"选项运行它们。然后,这个“紧密”算法无法定位标签并将扩展图形大小以包括它们。
我在此提出的解决方案是将注释的clip_on选项设置为True。这将防止在轴外部的注释可见。因此解决了对数尺度上零位置注释的问题。
import matplotlib.pyplot as plt
import seaborn as sns
titanic = sns.load_dataset('titanic')
ax1 = sns.distplot(titanic['fare'], kde=False, bins=15,)

ax1.set_yscale('log')

for p in ax1.patches:
    ax1.annotate(
        s=f"{p.get_height():1.0f}",
        xy=(p.get_x() + p.get_width() / 2., p.get_height()), 
        xycoords='data',
        ha='center', 
        va='center', 
        fontsize=11, 
        color='black',
        xytext=(0,7), 
        textcoords='offset points',
        clip_on=True,                   # <---  important
    )

plt.savefig("outfig.png", bbox_inches="tight")
plt.show()

clip_on 完成了。我已经搜索了将近一个小时了,终于找到了答案。谢谢! - KayO

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