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

如何用Seaborn distplot可视化高标准差数据的双侧尾部细节?

绘制高标准差双侧长尾数据分布的优化方案

问题背景

我有一个float类型的pd.Series,数据统计特征如下:

>>> pd.Series(foo).describe()
count    3.351198e+07
mean    -2.337614e+02
std      4.788547e+04
min     -9.999999e+06
25%      0.000000e+00
50%      0.000000e+00
75%      0.000000e+00
max      7.499913e+07

>>> pd.Series(foo).std()
47885.47066964969

数据高度集中在0值附近,但双侧存在明显长尾与异常值。当前使用sns.distplot(新版本seaborn建议用sns.histplot)结合对数刻度的方式仅对绝对值有效,无法细致观察双侧尾部的差异。

当前代码:

bins = [0, 10, 100, 1000, 10000, 100000, 100000, 100000000]
bins = [-i for i in bins[:1:-1] ] + bins
g = sns.distplot(foo.values,bins=bins,kde=False)
g.set_xscale('log')

优化方案

1. 拆分正负数据分别绘制对数直方图

将数据拆分为正值、负值(排除0),分左右子图绘制,直接对比双侧尾部的分布细节:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 拆分数据
positive_vals = foo[foo > 0]
negative_abs = foo[foo < 0].abs()  # 取绝对值适配对数刻度

# 创建子图
fig, (ax_neg, ax_pos) = plt.subplots(1, 2, figsize=(12, 5))

# 绘制负向尾部(绝对值)
sns.histplot(negative_abs, bins=[10**i for i in range(0, 8)], kde=False, ax=ax_neg)
ax_neg.set_xscale('log')
ax_neg.set_title('负向尾部(绝对值)')
ax_neg.set_xlabel('数值绝对值')
ax_neg.set_ylabel('频数')

# 绘制正向尾部
sns.histplot(positive_vals, bins=[10**i for i in range(0, 8)], kde=False, ax=ax_pos)
ax_pos.set_xscale('log')
ax_pos.set_title('正向尾部')
ax_pos.set_xlabel('数值')

plt.tight_layout()
plt.show()

2. 使用对称对数刻度(symlog)

matplotlib的symlog刻度可直接处理正负值,压缩0附近的刻度密度,放大尾部细节:

import seaborn as sns
import matplotlib.pyplot as plt

# 自定义对称区间bins
bins = [-1e7, -1e6, -1e5, -1e4, -1e3, -1e2, -10, 0, 10, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7]

g = sns.histplot(foo, bins=bins, kde=False)
# linthresh设置0附近线性刻度的范围,超出部分用对数刻度
g.set_xscale('symlog', linthresh=10)
g.set_title('对称对数刻度下的全数据分布')
plt.show()

这种方式保留了数值的正负方向,同时让尾部的细节清晰可见,0附近用线性刻度展示集中分布。

3. 分面网格精细化展示

通过分面网格分别展示0附近、负尾部、正尾部的分布,按需设置刻度:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 给数据打分组标签
df = pd.DataFrame({'value': foo})
df['group'] = pd.cut(df['value'], 
                     bins=[-1e8, -10, 0, 10, 1e8],
                     labels=['负尾部', '0附近负值', '0附近正值', '正尾部'])

# 绘制分面直方图
g = sns.FacetGrid(df, col='group', col_wrap=2, sharex=False, sharey=False)
g.map(sns.histplot, 'value', kde=False)

# 为尾部子图设置对数刻度
for ax, group_name in zip(g.axes, g.col_names):
    if group_name in ['负尾部', '正尾部']:
        ax.set_xscale('symlog' if group_name == '负尾部' else 'log')
    ax.set_title(group_name)

plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:01:03