如何用指定比例的两种颜色填充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
相关产品推荐
相关产品推荐

