【问题标题】:How to wrap long tick labels in a seaborn figure-level plot如何在 seaborn 图形级图中包装长刻度标签
【发布时间】:2021-08-27 12:09:45
【问题描述】:

我正在可视化调查结果。答案很长,我想将它们完全放入图表中。因此,如果您能指出一种使用多行 xticklabels 的方法,或者将 xticklabels 包含在侧面的图例中,我将非常感激,如本示例所示:

因为否则我必须使图表非常宽以适应整个答案。我当前的代码和结果图如下所示:

import seaborn as sns
from textwrap import wrap

sns.set(style="dark")
catp = (sns.catplot(data=results, x='1',
                    kind='count',
                    hue_order=results.sort_values('1')['1'],
                    palette='crest',
                    height=3.3,
                    aspect=17.4/7)
        .set(xlabel=None,
             ylabel='Number of Participants',
             title="\n".join(wrap("Question 1: Out of the three options, please choose the one you would prefer your fully autonomous car to choose, if you sat in it.", 90)))
)
plt.tight_layout()
catp.ax.set_yticks((0,10,20,30,40))
for p in catp.ax.patches:
    percentage = '{:.1f}%'.format(100 * p.get_height()/92)
    x = p.get_x() + p.get_width() / 2 - 0.05
    y = p.get_y() + p.get_height() + 0.3
    catp.ax.annotate(percentage, (x, y), size = 12)
plt.show()

最好的问候!

编辑:您可以使用以下代码创建示例数据框:

import pandas as pd
import numpy as np
from itertools import chain

x = (np.repeat('Brake and crash into the bus', 37),
np.repeat('Steer into the passing car on the left', 22),
np.repeat('Steer into the right hand sidewall', 39))

results = pd.DataFrame({'1': list(chain(*x))})

【问题讨论】:

    标签: python matplotlib plot graph seaborn


    【解决方案1】:
    • 提取xticklabels 并使用wrap 修复它们,就像使用title 一样
    • matplotlib 3.4.2 现在带有 .bar_label 以更轻松地注释条形图
      • 请参阅此answer 以自定义条形注释标签。
    • 图中的heightaspect 仍需要根据wrap width 进行一些调整。
    • 另一种解决方案是修复数据框中的值:
      • df['1'] = df['1'].apply(lambda row: '\n'.join(wrap(row, 30)))
      • for col in df.columns: df[col] = df[col].apply(lambda row: '\n'.join(wrap(row, 30))) 用于所有列。
    • labels 的列表推导使用赋值表达式 (:=),它需要 python >= 3.8。这可以重写为标准的 for 循环。
      • labels = [f'{v.get_height()/len(df)*100:0.1f}%' for v in c] 在没有赋值表达式的情况下工作,但不检查条形高度是否为 0。
    • python 3.8.11pandas 1.3.2matplotlib 3.4.2seaborn 0.11.2中测试
    import seaborn as sns
    from textwrap import wrap
    from itertools import chain
    import pandas as pd
    import numpy as np
    
    # sample dataframe
    x = (np.repeat('Brake and crash into the bus, which will result in the killing of the children on the bus, but save your life', 37),
    np.repeat('Steer into the passing car on the left, pushing it into the wall, saving your life, but killing passengers in the other car', 22),
    np.repeat('Steer into the right hand sidewall, killing you but saving the lives of all other passengers', 39))
    
    df = pd.DataFrame({'1': list(chain(*x))})
    
    # plotting
    sns.set(style="dark")
    catp = (sns.catplot(data=df, x='1',
                        kind='count',
                        hue_order=df.sort_values('1')['1'],
                        palette='crest',
                        height=5,
                        aspect=17.4/7)
            .set(xlabel=None,
                 ylabel='Number of Participants',
                 title="\n".join(wrap("Question 1: Out of the three options, please choose the one you would prefer your fully autonomous car to choose, if you sat in it.", 90)))
    )
    plt.tight_layout()
    catp.ax.set_yticks((0,10,20,30,40))
    
    for ax in catp.axes.ravel():
    
        # extract labels
        labels = ax.get_xticklabels()
        # fix the labels
        for v in labels:
            text = v.get_text()
            text = '\n'.join(wrap(text, 30))
            v.set_text(text)
        # set the new labels
        ax.set_xticklabels(labels)
        # annotate the bars
        for c in ax.containers:
    
            # create a custom annotation: percent of total
            labels = [f'{w/len(df)*100:0.1f}%' if (w := v.get_height()) > 0 else '' for v in c]
            
            ax.bar_label(c, labels=labels, label_type='edge')
    
    

    【讨论】:

    • 你真的很有帮助,非常感谢!
    • @Zwiebak 不客气。很高兴这对你有用。
    猜你喜欢
    • 2019-10-29
    • 2017-04-05
    • 2015-12-09
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 2017-12-25
    • 1970-01-01
    相关资源
    最近更新 更多