【问题标题】:Overlaying boxplots on the relative bin of a histogram在直方图的相对 bin 上叠加箱线图
【发布时间】:2022-01-05 18:43:29
【问题描述】:

以数据集'tip'为例

total_bill tip smoker day time size
16.99 1.01 No Sun Dinner 2
10.34 1.66 No Sun Dinner 3
21.01 3.50 No Sun Dinner 3
23.68 3.31 No Sun Dinner 2
24.59 3.61 No Sun Dinner 4

我要做的是表示变量“total_bill”的分布,并将其每个箱与链接的变量“tip”的分布相关联给它。在此示例中,此图旨在回答以下问题:“客户留下的小费分布与他们支付的账单的函数关系是什么?”

我或多或少地实现了我想要获得的图表(但是有一个问题。最后我解释一下它是什么)。
而我采用的程序是这样的:

  1. 将 'total_bill' 划分为 bin。

    tips['bins_total_bill'] = pd.cut(tips.total_bill, 10)
    tips.head()
    
    total_bill tip smoker day time size bins_total_bill
    16.99 1.01 No Sun Dinner 2 (12.618, 17.392]
    10.34 1.66 No Sun Dinner 3 (7.844, 12.618]
    21.01 3.50 No Sun Dinner 3 (17.392, 22.166]
    23.68 3.31 No Sun Dinner 2 (22.166, 26.94]
    24.59 3.61 No Sun Dinner 4 (22.166, 26.94]
  2. 使用以下方法创建 pd.Series:
    索引:pd.interval of total_cost bin
    值:出现次数

    s = tips['bins_total_bill'].value_counts(sort=False)
    s
    
(3.022, 7.844]       7
(7.844, 12.618]     42
(12.618, 17.392]    68
(17.392, 22.166]    51
(22.166, 26.94]     31
(26.94, 31.714]     19
(31.714, 36.488]    12
(36.488, 41.262]     7
(41.262, 46.036]     3
(46.036, 50.81]      4
Name: bins_total_bill, dtype: int64
  1. 将barplot和poxplot结合在一起

    fig, ax1 = plt.subplots(dpi=200)
    ax2 = ax1.twinx()
    
    sns.barplot(ax=ax1, x = s.index, y = s.values)
    sns.boxplot(ax=ax2, x='bins_total_bill', y='tip', data=tips)
    sns.stripplot(ax=ax2, x='bins_total_bill', y='tip', data=tips, size=5, color="yellow", edgecolor='red', linewidth=0.3)
    
    #Title and axis labels
    ax1.tick_params(axis='x', rotation=90)
    ax1.set_ylabel('Number of bills')
    ax2.set_ylabel('Tips [$]')
    ax1.set_xlabel("Mid value of total_bill bins [$]")
    ax1.set_title("Tips ~ Total_bill distribution")
    
    #Reference lines average(tip) + add yticks + Legend
    avg_tip = np.mean(tips.tip)
    ax2.axhline(y=avg_tip, color='red', linestyle="--", label="avg tip")
    ax2.set_yticks(list(ax2.get_yticks() + avg_tip))
    ax2.legend(loc='best')
    
    #Set labels axis x
    ax1.set_xticklabels(list(map(lambda s: round(s.mid,2), s.index)))
    

不得不说这张图有问题!由于 x 轴是分类的,例如,我不能在“total_bill”的平均值处添加一条垂直线。

如何解决此问题以获得正确的结果? 我也想知道是否有比我采用的更正确、更精简的方法。

【问题讨论】:

  • x 轴不是线性的,所以即使你把垂直线放在某个地方它也不会告诉你太多(这意味着,如果它在 15 和 19.78 之间的某个地方,如果比例) - 可能会突出显示其中的意思的垃圾箱?
  • 我的意思是,这是可行的——您应该获取相邻 x-ticks 的相对位置,然后在此基础上计算轴上均值的相对位置并用matplotlib.org/stable/api/_as_gen/… 绘制它.但这对理解数据没有多大帮助。
  • @DanielWlazło - 我完全同意你所说的!为了理解数据,突出显示 bin 就绰绰有余了。我提到的问题不是理解数据,而是熟悉可视化库。非常感谢您的回复!

标签: pandas matplotlib seaborn


【解决方案1】:

想到了这个方法,比上一个更紧凑(大概可以做得更好),并且克服了x轴缩放的问题。

  1. 我将 'total_bill' 拆分为 bin 并将列添加到 Df

    tips['bins_total_bill'] = pd.cut(tips.total_bill, 10)
    
  2. 将列“提示”按之前创建的 bin 分组

    obj_gby_tips = tips.groupby('bins_total_bill')['tip']
    gby_tip = dict(list(obj_gby_tips))
    
  3. 创建字典:
    键:每个 bin 间隔的中点
    值:每个间隔的 gby 提示

    mid_total_bill_bins = list(map(lambda bins: bins.mid, list(gby_tip.keys())))
    gby_tips = gby_tip.values()
    
    tip_gby_total_bill_bins = dict(zip(mid_total_bill_bins, gby_tips))
    
  4. 通过向箱线图的每个矩形传递 每个 bin 的质心

    fig, ax1 = plt.subplots(dpi=200)
    ax2 = ax1.twinx()
    
    bp_values = list(tip_gby_total_bill_bins.values())
    bp_pos = list(tip_gby_total_bill_bins.keys())
    
    l1 = sns.histplot(tips.total_bill, bins=10, ax=ax1)
    l2 = ax2.boxplot(bp_values, positions=bp_pos, manage_ticks=False, patch_artist=True, widths=2)
    
    #Average tips as hline
    avg_tip = np.mean(tips.tip)
    ax2.axhline(y=avg_tip, color='red', linestyle="--", label="avg tip")
    ax2.set_yticks(list(ax2.get_yticks() + avg_tip)) #add value of avg(tip) to y-axis
    
    #Average total_bill as vline
    avg_total_bill=np.mean(tips.total_bill)
    ax1.axvline(x=avg_total_bill, color='orange', linestyle="--", label="avg tot_bill")
    

然后是结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2021-10-29
    • 2016-01-24
    • 2020-10-10
    • 1970-01-01
    • 2021-05-19
    • 2014-03-31
    相关资源
    最近更新 更多