Python中使用Seaborn绘制角度分布PDF的边缘拟合问题
解决环形角度数据的PDF拟合问题
你的问题核心在于角度数据是环形(周期性)的,而Seaborn默认的KDE是为线性数据设计的,它不会考虑-180°和180°其实是同一个点,所以会在边缘出现密度衰减、过渡突兀的问题。下面是两种有效的解决方法:
方法1:使用专门的环形KDE(推荐)
利用scipy.stats中的circular_kde,它会直接处理数据的周期性,完美适配角度分布的拟合需求:
import numpy as np import seaborn as sns import matplotlib.pyplot as plt from scipy.stats import circular_kde def plot_circular_dist(angles_deg, color, label): # 将角度转换为弧度(circular_kde要求输入弧度) angles_rad = np.radians(angles_deg) # 创建环形KDE模型 kde_model = circular_kde(angles_rad) # 生成-180°到180°对应的弧度序列 x_rad = np.linspace(-np.pi, np.pi, 1000) # 计算密度值 density = kde_model(x_rad) # 转换回角度用于绘图 x_deg = np.degrees(x_rad) # 绘制直方图(保留原始数据的分布展示) sns.histplot(data=angles_deg, stat="density", bins=128, color=color, alpha=0.3) # 绘制环形KDE曲线 plt.plot(x_deg, density, color=color, linewidth=2, label=label) # 开始绘图 plt.figure(figsize=(10, 6)) for shear_val, color in zip(unique_shear_values, shear_palette_colors): subset = orientations[orientations['Shear'] == shear_val] plot_circular_dist(subset['Angle'], color, f'Shear: {shear_val}') plt.xlabel('Angle (°)') plt.ylabel('Density') plt.xlim(-180, 180) plt.legend() plt.show()
方法2:扩展数据模拟周期性
如果不想引入额外的工具,可以通过复制并平移数据,让普通KDE“误以为”数据是连续的线性序列,从而实现边缘的平滑过渡:
import numpy as np import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(10, 6)) for shear_val, color in zip(unique_shear_values, shear_palette_colors): subset = orientations[orientations['Shear'] == shear_val] angles = subset['Angle'] # 扩展数据:复制原始数据并分别平移±360°,让KDE连接-180°和180° extended_angles = np.concatenate([angles - 360, angles, angles + 360]) # 绘制原始数据的直方图 sns.histplot(data=angles, stat="density", bins=128, color=color, alpha=0.3) # 用扩展后的数据绘制KDE,最后只显示-180°到180°的范围 sns.kdeplot(data=extended_angles, color=color, linewidth=2, label=f'Shear: {shear_val}') plt.xlim(-180, 180) plt.xlabel('Angle (°)') plt.ylabel('Density') plt.legend() plt.show()
两种方法对比
- 环形KDE方法更专业,完全适配环形数据的统计特性,拟合精度更高,边缘过渡自然。
- 数据扩展方法更简洁,无需额外依赖,适合快速验证效果,但极端情况下的拟合准确度略逊于专门的环形KDE。
内容的提问来源于stack exchange,提问作者Asterion
相关产品推荐
相关产品推荐

