info() 查元数据(列名、dtype、non-null数、内存),非数据样貌;describe() 默认仅数值列统计,需include='all'才覆盖字符串;二者配合可发现类型陷阱与脏数据。

pd.DataFrame.info() 看什么、怎么看、为什么常被误读
info() 不是“看数据长啥样”的函数,它是查元数据的——列名、dtype、非空值数量、内存占用。很多人一上来就跑 info(),却没注意它默认不显示全部列(尤其列多时),也看不出数值分布或异常值。
- 加参数
verbose=True强制展开所有列;列太多时优先看memory_usage和non-null计数,快速定位缺失或类型错的字段 -
info()里的non-null是按列统计,不是按行;若某列有 999 个非空,不代表这 999 行其他列也全非空 - 注意
object类型:可能是字符串,也可能是混杂类型(比如数字+空字符串+None),这种列info()不报错,但后续astype(int)会崩 - 内存显示单位是字节,
memory_usage=12.4 MB这种输出容易被忽略,但大表里改int64为int32或category能省一半内存
pd.DataFrame.describe() 默认只算数值列,漏掉关键信息
describe() 默认只对 number 类型列生效,object 或 category 列直接消失。想看字符串列的频次、唯一值数?得主动加参数,否则等于白跑。
- 加
include='all'才会同时输出数值列的count/mean和字符串列的unique/top/freq - 数值列若含大量
NaN,describe()的count会明显小于行数,这是第一个线索:该列可能有脏数据 -
describe()的std对单值列返回NaN,不是 bug——标准差无定义;但如果你预期有波动却看到std=0.0,得检查是否全被转成字符串了(比如 “1”, “2”, “3”) - 时间列(
datetime64)默认也不在describe()结果里,要单独用df['col'].describe(datetime_is_numeric=True)或直接调min()/max()
info() 和 describe() 配合才能发现类型陷阱
一个常见坑:某列显示 non-null 1000 条,dtype 是 object,但 describe(include='all') 却显示 unique=1、top=' '(空格)。说明数据里塞满了空格、不可见字符或 'NULL' 字符串,而非真正的 NaN。
- 先用
info()锁定可疑object列,再用describe(include='all')看unique和top;若unique接近总行数但top是空值,大概率是脏字符串 - 验证用:
df['col'].str.strip().replace('', pd.NA).isna().sum()—— 先去空格再标空,比直接isna()更准 -
describe()的count对字符串列是“非空字符串数”,不等价于notna();''(空字符串)会被计入count,但info()的non-null也会把它当有效值
大表别无脑 info()/describe(),先 sample 再查
百万行以上数据,info() 和 describe() 本身不慢,但它们依赖完整扫描——尤其 describe(include='all') 对字符串列要遍历每行算 unique,极易卡住。
- 先
df.sample(10000).info()快速看结构;确认无异常后再跑全量 - 字符串列的
unique统计代价高,可用df['col'].nunique(dropna=False)替代describe()中的对应项,更快且可控 - Jupyter 里直接打
df.info?或df.describe?看签名,重点留意memory_usage(info)、percentiles(describe)这些易被跳过的参数
真正麻烦的从来不是函数不会用,而是 info() 说“非空”,describe() 说“有值”,结果一算均值就报 TypeError: unsupported operand type(s) for +: 'str' and 'int'——这时候得回头翻 dtype 和最原始的几行数据。

















