如何在同一画布基于迭代累积数据绘制多个boxen图
实现方案
不需要多次调用绘图接口叠加不同长度的数据集,只需要提前构造带明确x轴坐标的绘图数据集,即可一次性完成绘制,步骤如下:
- 遍历所有id,分别提取两类数据:当前id对应的独立value集合、id从0到当前id的累积value集合
- 给两类数据绑定预设的x轴坐标:独立分布放在整数x位置(和id值相等),累积分布放在对应id值+0.5的x位置
- 调用
seaborn.boxenplot时传入数值型x坐标列,通过hue区分两类分布,调整箱宽避免重叠,最后自定义x轴刻度对齐每个独立分布的位置即可
完整可运行代码:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # 构造示例数据 df = pd.DataFrame(columns=['id', 'value']) for id_val in range(5): df = pd.concat([ df, pd.DataFrame({'id': [id_val]*10, 'value':np.random.rand(10)}) ]).reset_index(drop=True) # 构造绘图数据集 plot_data = [] all_ids = sorted(df['id'].unique()) for curr_id in all_ids: # 1. 当前id的独立分布,x位置为curr_id single_data = df[df['id'] == curr_id][['value']].copy() single_data['x_pos'] = curr_id single_data['dist_type'] = '单id分布' plot_data.append(single_data) # 2. 从id=0到curr_id的累积分布,x位置为curr_id + 0.5 cum_data = df[df['id'] <= curr_id][['value']].copy() cum_data['x_pos'] = curr_id + 0.5 cum_data['dist_type'] = '累积分布' plot_data.append(cum_data) plot_df = pd.concat(plot_data).reset_index(drop=True) # 绘图 plt.figure(figsize=(12, 6)) sns.boxenplot( x='x_pos', y='value', hue='dist_type', data=plot_df, width=0.4, palette={'单id分布': '#1f77b4', '累积分布': '#ff7f0e'} ) # 调整x轴刻度,对齐单id分布的位置 plt.xticks(ticks=all_ids, labels=[f'id={i}' for i in all_ids]) plt.xlabel('id') plt.legend(title='分布类型') plt.tight_layout() plt.show()
效果说明
- id=0对应的x=0、x=0.5位置均为id=0的value分布,完全一致
- id=1对应的x=1位置为id=1独立分布,x=1.5位置为id0+id1的累积分布
- 后续id均按规则排布,两类分布左右相邻无重叠,可直观对比单id分布和截至当前id的累积分布差异
内容的提问来源于stack exchange,提问作者Esi
相关产品推荐
相关产品推荐

