以数据集'tip'为例
我想做的是表示变量“total_bill”的分布,并将其每个容器与链接的变量“tip”的分布相关联给它。在此示例中,此图旨在回答以下问题:“客户留下的小费随他们支付的账单的分布情况如何?”
我已经或多或少地实现了我想要获得的图表(但是有一个问题,最后我解释它是什么)。
而我采用的流程是这样的:
将“total_bill”分成多个箱子。
tips['bins_total_bill'] = pd.cut(tips.total_bill, 10) tips.head()
<表类="s-表"> <头>total_bill 提示 吸烟者 <日>日日> <次>次次>大小 bins_total_bill 16.99 1.01 没有 太阳 晚餐 2 (12.618, 17.392] 10.34 1.66 没有 太阳 晚餐 3 (7.844, 12.618] 21.01 3.50 没有 太阳 晚餐 3 (17.392, 22.166] 23.68 3.31 没有 太阳 晚餐 2 (22.166, 26.94] 24.59 3.61 没有 太阳 晚餐 4 (22.166, 26.94] 使用以下内容创建 pd.Series:
索引:total_cost bins 的 pd.interval
值:出现次数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
结合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轴上缩放的问题。
我将“total_bill”拆分为 bin 并将该列添加到 Df
tips['bins_total_bill'] = pd.cut(tips.total_bill, 10)
按之前创建的 bin 对列“tip”进行分组
obj_gby_tips = tips.groupby('bins_total_bill')['tip'] gby_tip = dict(list(obj_gby_tips))
创建字典:
keys:每个bins间隔的中点
values: gby tips for each intervalmid_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))
通过传递给箱线图的每个矩形来创建图表 每个相应箱子的质心
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")
然后是结果。
关于pandas - 在直方图的相对 bin 上叠加箱线图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70598044/