df.describe()默认不包含中位数、偏度、极端分位数,忽略异常值影响,跳过非数值列,分组后结构易混淆,需用agg()、value_counts()等补充关键信息。

df.describe() 能快速给出数值列的常规统计量,但默认不包含中位数、偏度、分位数等关键指标,直接调用往往漏掉异常值和分布形态信息。
为什么 describe() 默认结果常不够用
它只对数值型列生效,自动跳过字符串或类别型字段;默认只返回 0.25/0.5/0.75 分位数,无法看到 0.9 或 0.01 这类极端分位;标准差和均值在存在异常值时会严重失真,而 describe() 不提示这一点。
- 若列含大量
NaN,count值偏低但不会警告缺失比例是否超 30% - 对偏态数据(如用户消费金额),
mean和median差距大,但默认输出里没并列对比 -
describe(include='all')会尝试处理非数值列,但对字符串只返回count、unique、top、freq,无法做词频分布或长度统计
agg() 自定义聚合比 describe() 更灵活
当你需要特定组合——比如同时看浏览时长的中位数和 90% 分位数、购买金额的 IQR 和偏度——agg() 是更直接的选择。
- 传入字典:如
{'browse_duration': ['median', lambda x: x.quantile(0.9)], 'purchase_amount': ['std', 'skew']} - 可混用内置字符串(
'mean')和匿名函数,避免重复写.median()等方法调用 - 注意:lambda 函数返回标量,不能返回 Series,否则结果对齐会出错
- 若某列全为
NaN,对应聚合结果为NaN,不会报错但需人工检查
别忽略非数值列的描述性信息
用户 ID、商品类目、地区编码这类字段,describe() 的 include='all' 只给基础频次,远不够诊断数据质量。
- 用
value_counts(normalize=True).head(5)查前 5 名占比,识别是否某类目占 80% - 对字符串列,加
.str.len().describe()看长度分布,能发现异常空值或超长乱码 -
nunique()比unique更实用——它返回去重后数量,配合len()可算重复率 - 类别型字段建议先
astype('category'),再用cat.categories和cat.codes检查编码完整性
分组后描述统计容易误用 axis
用 groupby().describe() 时,输出是多级索引 DataFrame,各统计量被压成列,初学者常误以为它是“按组逐行展示”,其实结构是“每组 × 每个统计量 × 每列”。
- 真正想看每组内各列的中位数?直接
groupby('region')[['amount', 'duration']].median() -
describe()在 groupby 后默认仍按列聚合(axis=0),改axis=1会导致逻辑混乱,基本不用 - 若 groupby 后接
agg(),推荐用命名元组方式:agg([('med', 'median'), ('iqr', lambda x: x.quantile(0.75) - x.quantile(0.25))]),结果列名清晰可读
实际跑一遍 describe() 很快,但真正有用的描述性统计,取决于你是否主动绕开它的默认路径——尤其是中位数缺省、非数值列信息贫乏、分组结构易混淆这三点,最容易在第一次探索时埋下误判隐患。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











