使用对数刻度注释 seaborn distplot 会引发错误

Tro*_*roy 6 python matplotlib python-3.x seaborn

%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',
    )
Run Code Online (Sandbox Code Playgroud)

上面的代码绘制了泰坦尼克号数据集的直方图Fare,其中每个条形都使用 注释了其值ax1.annotate。当我想将 y 刻度设置为 logc 时,麻烦就来了——取消注释该set_yscale行并运行它;它抛出一个错误说:

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

也许应该更改 xycoords 参数,但我也不太确定要更改什么。

我使用的是Python 3.7.2,seaborn的版本是0.9.0。Matplotlib 版本 3.0.2,我使用的是内联后端。

Imp*_*est 6

一些注释放在y=0. 这将导致位置在对数刻度上未定义。
在具有内联后端的 jupyter 笔记本中,显示图形的默认选项是通过 选项运行bbox_inches="tight"它们savefig。这种“严格”的算法无法找到标签,并且无论如何都会扩展图形大小以包含它们。

我在这里建议的解决方案是将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()
Run Code Online (Sandbox Code Playgroud)