如何在Python中基于给定数据绘制散点饼图(Scatter Pie Plot)
Python实现散点饼图(Scatter Pie Plot)方案
需求背景
现有两组业务数据:
- 客户-门店购买占比数据:
# 样本数据1:客户在各门店的购买占比 import pandas as pd df = pd.DataFrame({ 'x': [1,1,2,2], 'y': [2,3,2,3], 'Share': [0.834437, 0.165562, 0.966749, 0.033250] })
字段说明:
x:客户编号y:门店IDShare:客户在对应门店的购买占比(单客户的Share总和接近1)门店-产品细分占比数据:
# 样本数据2:各门店内不同产品的购买占比 df2 = pd.DataFrame({ 'x': [1,1,1,1,2,2,2,2], 'y': [2,2,3,3,2,2,3,3], 'product': ['A','B','A','B','A','B','A','B'], 'ProdShare': [0.863095, 0.136904, 0.940000, 0.060000, 0.842494, 0.157505, 0.925233, 0.074766] })
字段说明:
product:产品类型(仅A、B两类)ProdShare:对应产品在门店内的购买占比(单门店的ProdShare总和接近1)
需要绘制散点饼图:每个圆形的大小对应客户在该门店的Share占比,圆形内部用红色表示产品A的占比,黄色表示产品B的占比。
实现步骤
1. 数据预处理:合并两组数据
首先将产品细分数据转换为宽表,再与客户-门店占比数据合并,得到每个(x,y)组合对应的Share和产品A/B的占比:
# 将df2转换为宽表,每个(x,y)对应A、B的ProdShare merged_df = df2.pivot(index=['x', 'y'], columns='product', values='ProdShare').reset_index() # 合并到df中,得到完整数据集 merged_df = pd.merge(df, merged_df, on=['x', 'y'])
2. 使用Matplotlib绘制散点饼图
核心逻辑是在指定坐标位置(用客户编号x和门店IDy作为坐标)绘制饼图,饼图大小由Share控制,扇区占比对应产品A/B的ProdShare:
import matplotlib.pyplot as plt # 创建画布和坐标轴 fig, ax = plt.subplots(figsize=(8, 6)) # 定义颜色:产品A用红色,产品B用黄色 color_map = ['#ff4444', '#ffdd44'] product_labels = ['产品A', '产品B'] # 遍历每条记录绘制饼图 for _, row in merged_df.iterrows(): # 饼图的中心坐标 center_pos = (row['x'], row['y']) # 饼图大小:Share乘以缩放系数(这里用1000,可根据视觉效果调整) pie_size = row['Share'] * 1000 # 产品A、B的占比 prod_ratios = [row['A'], row['B']] # 绘制饼图 wedges, _ = ax.pie( prod_ratios, colors=color_map, radius=pie_size / 1000, # 半径与Share成正比 center=center_pos, textprops={'fontsize': 8} ) # 可选:添加Share占比的文本标签 ax.text( center_pos[0], center_pos[1] + pie_size/1000 + 0.1, f"占比: {row['Share']:.2%}", ha='center', fontsize=10 ) # 配置坐标轴与标题 ax.set_xlabel('客户编号', fontsize=12) ax.set_ylabel('门店ID', fontsize=12) ax.set_xlim(0.5, 2.5) # 调整范围确保所有饼图显示完整 ax.set_ylim(1.5, 3.5) ax.set_aspect('equal') # 保持坐标轴比例一致,避免饼图变形 ax.legend(wedges, product_labels, loc='upper right', bbox_to_anchor=(1.3, 1)) plt.title('客户-门店购买占比散点饼图', fontsize=14) plt.show()
关键说明
- 用
pivot转换df2是为了让每个(x,y)组合对应一行,方便后续遍历绘制饼图。 radius参数直接关联Share值,通过缩放系数调整饼图的整体大小,可根据实际需求修改。set_aspect('equal')是必须的,否则饼图会因为坐标轴比例问题被拉伸变形。
内容的提问来源于stack exchange,提问作者nasim_bbb
相关产品推荐
相关产品推荐

