首页 > 解决方案 > 具有水平着色的 Seaborn 直方图

问题描述

我正在尝试绘制几个直方图,plt.subplots()如下所示:

chart_len  = 15
chart_height = 25

fig, axs = plt.subplots(len(weight_classes),figsize=(chart_len,chart_height))

sns.set_theme(style="darkgrid",font_scale=2.5)
colors = sns.color_palette('GnBu_d',len(weight_classes)+1)
 
for i, wc in enumerate(activity_wc):
        data = activity_wc[wc]
        bins = [i for i in range(0,data['total_strikes_attempted'].max(),5)]
        
        sns.histplot(data,x='total_strikes_attempted', bins=bins, ax=axs[i], kde=True, stat='probability', color=colors[-(i+2)]) 
      

这将检索此图像: histogram subplots

我想要的是让条形图使用调色板,所以它们会水平改变颜色。有谁知道如何做到这一点?

标签: matplotlibseaborn

解决方案


ax.containers[0]包含所有直方图条。您可以遍历它们并设置单独的颜色。范数(将 x 值映射到 0-1 范围)可以基于第一个和最后一个 bin 边界。

基本上,代码如下所示:

ax = sns.histplot(...)
norm = plt.Normalize(bins[0], bins[-1])
cmap = sns.color_palette('GnBu_d', as_cmap=True) # use 'GnBu_r_d' for the reversed map
for bar in ax.containers[0]:
    bar.set_color(cmap(norm(bar.get_x())))   

假设activity_wc是 的结果activity.groupby('weight_class'),则可以更直接地从原始数据帧中获得该图。sns.displotwithrow='weight_class'将负责分组并创建子图网格。请注意,这figsize将由height=单个子图的高度和一个子图aspect=的纵横比(宽度除以高度)控制。

这是一个从虚拟数据开始的示例。请注意,bin 开始时刚好小于零以避免舍入误差,并且添加了一个 bin 边缘以确保最高值落入最后一个 bin。(sns.displot(..., facet_kws={'sharex':False})用于为每个子图设置 x-tick 标签。)

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

weight_classes = ['Flyweight', 'Bantamweight', 'Featherweight', 'Lightweight', 'Welterweight',
                  'Middleweight', 'Light Heavyweight', 'Heavyweight']
activity = pd.DataFrame({'weight_class': np.random.choice(weight_classes, 1000),
                         'total_strikes_attempted': np.concatenate([np.random.binomial(120, p, 100)
                                                                    for p in np.linspace(0.2, 0.9, 10)])})
sns.set_theme(style="darkgrid", font_scale=0.8)

bins = np.arange(-0.00001, max(activity['total_strikes_attempted']) + 5, 5)
g = sns.displot(data=activity, x='total_strikes_attempted',
                row='weight_class', row_order=weight_classes,
                kind='hist', stat='probability', kde=True, palette='GnBu_d',
                height=1.6, aspect=3)
norm = plt.Normalize(bins[0], bins[-1])
cmap = sns.color_palette('GnBu_d', as_cmap=True) # use 'GnBu_r_d' for the reversed map
for ax in g.axes.flat:
    ax.margins(x=0) # less white space left and right
    for bar in ax.containers[0]:
        bar.set_color(cmap(norm(bar.get_x())))
plt.tight_layout()
plt.show()

改变条形颜色的显示


推荐阅读