You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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:门店ID

  • Share:客户在对应门店的购买占比(单客户的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:37:50