如何用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




