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

如何用指定比例的两种颜色填充Matplotlib散点图标记

嘿,刚好我之前处理过类似的需求,给你两个可行的解决方案,帮你实现自定义填充比例的散点标记,或者用饼图当标记~

方案一:自定义填充比例的扇形标记(高效直观)

这个方法用matplotlib的扇形(Wedge)组件组合出带占比的标记,能精确控制两种颜色的填充比例,而且性能很好,适合大数据量。

完整代码示例

import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.patches as patches

# 模拟你的DataFrame结构(替换成你实际的数据)
df = pd.DataFrame({
    'regions': ['North', 'South', 'East', 'West', 'North'],
    'x': [1, 2, 3, 4, 5],
    'y': [10, 8, 12, 9, 11],
    'fill_pct': [35, 60, 20, 75, 50]  # 自定义的填充占比(0-100)
})

fig, ax = plt.subplots(figsize=(16,7))

# 给不同区域设置专属的颜色对(适配你原来按region循环的逻辑)
region_colors = {
    'North': ('#1f77b4', '#ff7f0e'),
    'South': ('#2ca02c', '#d62728'),
    'East': ('#9467bd', '#8c564b'),
    'West': ('#e377c2', '#7f7f7f')
}

# 控制标记大小(数值越大标记越大)
marker_size = 1200

for idx, row in df.iterrows():
    x, y, pct = row['x'], row['y'], row['fill_pct']
    region = row['regions']
    color1, color2 = region_colors[region]
    
    # 计算扇形对应的角度(占比转成360度制)
    fill_angle = pct / 100 * 360
    # 根据标记大小计算半径(确保大小和视觉效果匹配)
    radius = (marker_size ** 0.5) / 22
    
    # 绘制占比部分的扇形
    wedge_fill = patches.Wedge((x, y), radius, 0, fill_angle, facecolor=color1, edgecolor='white', linewidth=0.8)
    ax.add_patch(wedge_fill)
    # 绘制剩余部分的扇形
    wedge_rest = patches.Wedge((x, y), radius, fill_angle, 360, facecolor=color2, edgecolor='white', linewidth=0.8)
    ax.add_patch(wedge_rest)

# 调整坐标轴范围,确保所有标记都完整显示
ax.set_xlim(df['x'].min() - 0.8, df['x'].max() + 0.8)
ax.set_ylim(df['y'].min() - 0.8, df['y'].max() + 0.8)
plt.title('Scatter Plot with Custom Fill Percentage')
plt.show()

关键说明

  • 每个标记由两个扇形拼接而成,角度完全由你的fill_pct列控制,想设多少占比就设多少
  • 通过region_colors字典可以给不同区域设置不同的颜色组合,完美适配你原来按region循环的逻辑
  • 标记大小和半径的对应关系可以通过调整radius计算里的除数来微调,找到你最满意的视觉效果
方案二:用迷你饼图作为散点标记(更直观的多类别展示)

如果你的需求不止两种颜色,或者想更直观地展示占比,这个方法会更合适——在每个散点的位置绘制一个迷你饼图作为标记。

完整代码示例

import matplotlib.pyplot as plt
import pandas as pd

# 模拟你的DataFrame结构
df = pd.DataFrame({
    'regions': ['North', 'South', 'East', 'West'],
    'x': [1, 2, 3, 4],
    'y': [10, 8, 12, 9],
    'fill_pct': [35, 60, 20, 75]
})

fig, ax = plt.subplots(figsize=(16,7))

# 饼图大小(根据你的坐标轴范围调整,数值越大饼图越大)
pie_dim = 0.15

# 区域颜色配置
region_colors = {
    'North': ('#1f77b4', '#ff7f0e'),
    'South': ('#2ca02c', '#d62728'),
    'East': ('#9467bd', '#8c564b'),
    'West': ('#e377c2', '#7f7f7f')
}

for idx, row in df.iterrows():
    x, y, pct = row['x'], row['y'], row['fill_pct']
    region = row['regions']
    colors = region_colors[region]
    
    # 在当前点位置创建嵌入子图
    pie_ax = ax.inset_axes([x - pie_dim/2, y - pie_dim/2, pie_dim, pie_dim])
    # 绘制迷你饼图,展示占比和剩余部分
    pie_ax.pie([pct, 100-pct], colors=colors, wedgeprops={'linewidth':0.5})
    # 隐藏子图的坐标轴,只保留饼图
    pie_ax.axis('off')

# 调整坐标轴范围
ax.set_xlim(df['x'].min() - 0.8, df['x'].max() + 0.8)
ax.set_ylim(df['y'].min() - 0.8, df['y'].max() + 0.8)
plt.title('Scatter Plot with Pie Chart Markers')
plt.show()

关键说明

  • 用inset_axes在每个散点坐标处生成小画布,然后绘制饼图,视觉上就是饼图作为标记
  • 如果需要展示超过两种类别,只需要修改pie函数的输入列表和对应的颜色列表即可
  • 注意:如果你的数据量很大(比如上千个点),这个方法的性能会稍差,因为每个饼图都是独立的子图,此时方案一会更合适

内容的提问来源于stack exchange,提问作者Charlotte

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:21:30