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

如何让Matplotlib散点图图例尺寸固定在0-100范围?

问题

使用Matplotlib绘制散点图时,希望图例固定展示代表[0,25,50,75,100]的点尺寸,但scatter.legend_elements()函数会基于实际数据范围生成归一化的图例值。当前数据中Percentage变量范围仅为0-15,需要实现无论该变量实际范围如何,图例始终显示0-100的尺寸对应关系。

原代码如下:

import sys
def make_scatter_plot_by_tissue(df, size_legend="auto"):
    #sort df by Percentage
    df=df.sort_values(by=['Percentage'], ascending=False)
    genes = df.Genes.unique()
    if len(genes) > 1:
        sys.stderr.write("check there is only one gene\n")
    else:
        gene = genes[0]
    plt.figure(figsize = (20,20))
    scatter_plot = plt.scatter(df['Genes'], df['Groups'],
                            s=df['Percentage'], c=df['Average rank'], # size of points based on percentage
                            cmap='Reds', alpha=0.7)
    # Add a colorbar to show the mapping of colors to values
    cbar = plt.colorbar(scatter_plot)
    cbar.set_label('Average Rank', fontsize=20)
    #set the cbar legend range to be 0-5000
    plt.clim(0, 5000)
    #set the cbar label font size
    cbar.ax.tick_params(labelsize=20)
    # code based on this https://stackoverflow.com/a/58485655/1735942
    # Create a custom legend with circles representing the dot sizes
    # how to make the num range between 0-100 no matter the range of Percentage variable?
    size_legend = plt.legend(*scatter_plot.legend_elements(prop="sizes", num="auto"), 
                         loc='center left', title='Percentage', bbox_to_anchor=(1.30, .5), fontsize=15)
    # Set the title for the size legend
    size_legend.set_title('Percentage')
    size_legend.get_title().set_fontsize('20')
    # Display the plot
    plt.yticks(fontsize=15)
    plt.xticks(fontsize=15, rotation=90)
    plt.xlabel('Genes', fontsize=20)
    plt.ylabel('Tissue type', fontsize=20)
    title_string=f"Tissue expression summmary {gene}"
    plt.title(title_string, fontsize=20)
    plt.show()
解决方案

放弃legend_elements()的自动生成逻辑,手动创建固定范围的尺寸图例:

  • 定义目标图例值:target_sizes = [0,25,50,75,100]
  • 为每个目标值创建对应大小的散点标记(利用matplotlib.lines.Line2D生成圆形标记)
  • 手动关联标记与标签,创建自定义图例
修改后的完整代码
import sys
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

def make_scatter_plot_by_tissue(df, size_legend="auto"):
    # sort df by Percentage
    df = df.sort_values(by=['Percentage'], ascending=False)
    genes = df.Genes.unique()
    if len(genes) > 1:
        sys.stderr.write("check there is only one gene\n")
    else:
        gene = genes[0]
    
    plt.figure(figsize=(20,20))
    scatter_plot = plt.scatter(df['Genes'], df['Groups'],
                            s=df['Percentage'], c=df['Average rank'],
                            cmap='Reds', alpha=0.7)
    
    # 处理颜色条
    cbar = plt.colorbar(scatter_plot)
    cbar.set_label('Average Rank', fontsize=20)
    plt.clim(0, 5000)
    cbar.ax.tick_params(labelsize=20)
    
    # 创建固定范围的尺寸图例
    target_sizes = [0,25,50,75,100]
    # 生成图例标记:每个标记对应目标尺寸,样式匹配散点图
    legend_markers = [
        Line2D([0], [0], marker='o', color='w', markerfacecolor='red', 
               markersize=pow(s, 0.5), alpha=0.7, label=str(s)) 
        for s in target_sizes
    ]
    # 创建图例
    size_legend = plt.legend(handles=legend_markers, 
                             loc='center left', title='Percentage', 
                             bbox_to_anchor=(1.30, .5), fontsize=15)
    size_legend.get_title().set_fontsize('20')
    
    # 设置图表其他属性
    plt.yticks(fontsize=15)
    plt.xticks(fontsize=15, rotation=90)
    plt.xlabel('Genes', fontsize=20)
    plt.ylabel('Tissue type', fontsize=20)
    plt.title(f"Tissue expression summary {gene}", fontsize=20)
    plt.show()

说明

  • 用Line2D生成圆形标记时,markersize取尺寸值的平方根,因为Matplotlib中scatter的s参数代表点的面积,而markersize代表点的直径,以此匹配视觉大小
  • 标记的颜色、透明度与原散点图保持一致,确保视觉统一
  • 目标尺寸列表可根据需求自由调整,不受实际数据范围影响

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:22:51