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

如何归一化DataFrame的sizes列以用于散点图尺寸映射?

解决方案

先给你划个关键细节:matplotlib的scatter函数里,s参数控制的是标记的面积,而我们人眼对“大小”的感知其实是基于直径这种线性维度的——这也是你用对数变换后觉得差异太小的核心原因之一。结合你要保留原数据比例+视觉差异明显的需求,推荐这两种实用方法:

1. 线性归一化(严格保留数据比例)

这种方法直接把原始sizes数据线性映射到你指定的视觉舒适区间(比如20到500,可根据图表大小灵活调整),完全保留原始数据的比例关系,不会压缩或放大任何区间的差异,是最直接的解决方案。

代码实现:

import matplotlib.pyplot as plt
import numpy as np

n = 50
x = np.random.randn(n)
y = x * np.random.randn(n)
sizes = (np.random.randn(n) * 8) ** 2

def linear_normalize(data, min_size=20, max_size=500):
    data_min = data.min()
    data_max = data.max()
    # 处理所有数据相同的边界情况
    if data_max == data_min:
        return np.full(len(data), (min_size + max_size) // 2)
    # 线性映射到目标范围
    return (data - data_min) / (data_max - data_min) * (max_size - min_size) + min_size

# 生成归一化后的尺寸
normalized_sizes = linear_normalize(sizes)

# 绘制散点图
fig, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, s=normalized_sizes)
plt.show()

2. 平方根变换+线性归一化(更贴合视觉感知)

如果你的sizes数据代表的是某种“线性量级”(比如长度、数量),直接用面积的话,视觉上的大小差异会比实际数据比例大(比如数据从2变到8,面积是4倍,但直径只是2倍)。先做平方根变换把数据转成“直径维度”,再归一化,最后转回面积,能让视觉感知的大小比例更匹配原始数据的比例。

代码实现:

def sqrt_normalize(data, min_size=20, max_size=500):
    # 先把面积转成对应的直径(平方根)
    sqrt_data = np.sqrt(data)
    data_min = sqrt_data.min()
    data_max = sqrt_data.max()
    
    if data_max == data_min:
        return np.full(len(data), (min_size + max_size) // 2)
    
    # 把直径归一化到目标范围对应的直径区间
    normalized_diam = (sqrt_data - data_min)/(data_max - data_min) * (np.sqrt(max_size) - np.sqrt(min_size)) + np.sqrt(min_size)
    # 转回面积作为s参数
    return normalized_diam ** 2

sqrt_norm_sizes = sqrt_normalize(sizes)

fig, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, s=sqrt_norm_sizes)
plt.show()

为什么对数归一化不适合你的场景?

对数变换的核心作用是压缩大数值之间的差异,只有当你的数据跨度极端大(比如从1到100000)时,才需要用它来避免超大标记覆盖其他数据。但你的数据跨度没那么极端,所以对数变换会把原本应该有的大小差异抹平,导致视觉上区分度不够——这就是你遇到的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:17:33