You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Matplotlib实现散点图的密度渐变叠加效果?

实现散点图密度渐变(密度越高越黑)的解决方案

Got it,你想要的那种密度越高颜色越趋近黑色的散点图效果,单纯靠统一设置alpha参数确实很难实现——因为alpha只会让所有点保持相同的透明度,没法根据局部点的密度动态调整颜色深浅。下面给你两个实用的Matplotlib方案,完美匹配你的需求:


方案1:核密度估计(KDE)+ 动态颜色映射

适合需要保留单个散点形态,同时体现局部密度的场景,能精准实现“密度高→黑色,密度低→浅色”的效果。

修改后的代码

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde

# 加载你的数据
cat = np.genfromtxt('cat.txt')
x = cat[:, 3]
y = cat[:, 9]

# 计算每个点的局部密度值
# 堆叠x和y坐标,用于KDE计算
xy_coords = np.vstack([x, y])
kde_model = gaussian_kde(xy_coords)
point_density = kde_model(xy_coords)

# 按密度排序:让高密度点绘制在顶层,避免被低密度点遮挡
sorted_indices = point_density.argsort()
x_sorted = x[sorted_indices]
y_sorted = y[sorted_indices]
density_sorted = point_density[sorted_indices]

# 绘制散点图,用密度值映射颜色
fig, ax = plt.subplots(1, 1)
# 使用反转灰度色卡(Greys_r):密度越高颜色越黑;alpha保留一定透明度避免完全糊死
scatter_plot = ax.scatter(
    x_sorted, y_sorted,
    marker='.', zorder=3,
    c=density_sorted, cmap='Greys_r', alpha=0.8
)
ax.grid(ls=':', zorder=0)

# 添加颜色条,直观展示密度与颜色的对应关系
plt.colorbar(scatter_plot, label='Local Point Density')
plt.show()

关键说明

  • gaussian_kde会计算每个点周围的局部点密度,把这个值作为颜色参数c,就能让颜色随密度动态变化
  • Greys_r是反转的灰度色卡,默认Greys是黑到白,反转后正好是密度越高颜色越黑
  • 对密度排序是为了让高密度点在绘制顺序的顶层,避免被大量低密度点遮挡,优化视觉效果

方案2:六边形密度热力图(hexbin)

适合数据量极大的场景,视觉上更整洁,类似TopCAT生成的聚合式密度图效果。

代码示例

import matplotlib.pyplot as plt
import numpy as np

cat = np.genfromtxt('cat.txt')
x = cat[:, 3]
y = cat[:, 9]

fig, ax = plt.subplots(1, 1)
# 绘制六边形密度图:gridsize控制格子大小,bins='log'适配不均匀的数据分布
hexbin_plot = ax.hexbin(
    x, y, gridsize=50,
    cmap='Greys_r', bins='log', zorder=3
)
ax.grid(ls=':', zorder=0)

plt.colorbar(hexbin_plot, label='Number of Points per Hexagon')
plt.show()

关键说明

  • hexbin会把画布分成六边形网格,统计每个网格内的点数,用颜色深浅表示密度
  • bins='log'适合数据分布极不均匀的情况(大部分区域点少,少数区域点极多),能让颜色梯度更明显

自定义颜色渐变(可选)

如果你想要类似TopCAT的红色渐变到黑色效果,可以自定义颜色映射:

from matplotlib.colors import LinearSegmentedColormap

# 自定义从浅红→深红→黑色的渐变
red_black_cmap = LinearSegmentedColormap.from_list(
    'red_to_black',
    ['#ffeeee', '#cc2222', '#000000']  # 浅红、深红、黑色的十六进制色值
)
# 然后把上述代码中的cmap参数换成red_black_cmap即可

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

火山引擎 最新活动