3. 数据剖析与探索:用Pandas给你的数据做个“体检”

拿到一份历史数据,别急着动手清洗。我个人的习惯是——先“望闻问切”。

什么意思?就是先全面了解数据长什么样,有什么毛病,再对症下药。这一步,我们叫数据剖析与探索。说白了,就是给你的数据做个全面体检。

Pandas里有一整套工具,能让你快速摸清数据的底细。今天我就带你过一遍最常用的几个:head()info()describe()shapedtypes

核心逻辑:先看整体结构,再看统计特征,最后定位异常。这是数据清洗的黄金三步。

数据剖析与探索 结构概览 shape, dtypes, info() 数据预览 head(), tail(), sample() 统计描述 describe(), value_counts() 行数×列数 字段类型 前5行预览 随机抽样 数值统计 频次统计 目标:发现缺失、异常、类型错误

3.1 先看整体:shape 和 dtypes

每次加载完数据,我第一件事就是敲两行代码:df.shapedf.dtypes。为什么?因为这两个东西能告诉你最基础的信息——数据有多大,每列是什么类型。

import pandas as pd

# 加载历史订单数据
df = pd.read_csv('orders_history.csv')

# 看形状
print(df.shape)
# 输出:(50000, 12)  —— 5万行,12列

# 看字段类型
print(df.dtypes)

输出结果大概长这样:

字段名类型
order_idint64
customer_nameobject
order_dateobject
amountfloat64
statusobject

注意:看到 order_date 是 object 类型了吗?这说明日期被读成了字符串。我在项目中遇到过好几次,因为日期格式不统一,导致后续分析全乱套。所以这一步就能发现类型问题。

你想想看,如果 amount 字段显示的是 object 而不是 float64,那说明里面有脏数据——比如混入了"待确认"这样的文本。这就是清洗的信号。

3.2 快速预览:head() 和 tail()

head() 默认显示前5行。我习惯先看前5行,再看后5行,这样能快速感知数据的两端有没有异常。

# 看前5行
print(df.head())

# 看后5行
print(df.tail())

# 随机看10行(我特别喜欢这个)
print(df.sample(10))

为什么要用 sample()?因为有时候数据是按时间排序的,只看头尾可能漏掉中间的问题。随机抽样能帮你发现一些“隐藏的惊喜”。

小技巧:如果数据量很大(比如上百万行),head(100) 就够了。别傻乎乎地打印全部,你的终端会卡死的。我曾经手滑过一次……嗯,等了半分钟才缓过来。

3.3 全面体检:info()

info() 是我最常用的函数,没有之一。它一次性告诉你:总行数、每列的非空数量、数据类型、内存占用。简直就是数据体检报告。

print(df.info())

输出示例:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 50000 entries, 0 to 49999
Data columns (total 12 columns):
 #   Column         Non-Null Count  Dtype  
---  ------         --------------  -----  
 0   order_id       50000 non-null  int64  
 1   customer_name  49800 non-null  object 
 2   order_date     50000 non-null  object 
 3   amount         49500 non-null  float64
 4   status         49000 non-null  object 
dtypes: float64(1), int64(1), object(3)
memory usage: 4.6+ MB

看到问题了吗?customer_name 只有49800条非空,说明有200条缺失。status 更夸张,少了1000条。这些就是清洗的重点对象。

关键指标:Non-Null Count 如果小于总行数,就说明有缺失值。缺失比例超过5%的字段,要特别关注。

3.4 统计摘要:describe()

describe() 默认只对数值型列做统计。它会给出:计数、均值、标准差、最小值、四分位数、最大值。这些数字能帮你快速发现异常值。

print(df.describe())

输出示例:

order_idamount
count50000.049500.0
mean25000.5356.78
std14433.81200.45
min1.0-500.0
25%12500.050.0
50%25000.0150.0
75%37500.0400.0
max50000.099999.0

看到 amount 的最小值是 -500 了吗?金额怎么可能为负?这明显是异常值。再看最大值 99999,均值才356,这明显是个离群点。

避坑指南:我曾经接手过一份销售数据,describe() 显示某个字段的 max 值比 75% 分位数大了100倍。后来一查,是有人录入时多按了个0。这种错误靠肉眼根本看不出来,但统计摘要一眼就能发现。

如果想看非数值列的统计,可以加个参数:

print(df.describe(include='object'))

这样会显示:频次最高的值(top)、出现次数(freq)、唯一值个数(unique)。比如 status 字段,如果唯一值有50个,那肯定有问题——订单状态一般就三四种。

3.5 实战组合拳

好了,上面这些工具单独用都很简单。但真正的高手,是把它们组合起来用。我一般按这个顺序来:

  1. 先看 shape —— 确认数据量是否合理。比如预期10万行,结果只有1万行,那加载可能有问题。
  2. 再看 dtypes —— 检查类型是否匹配。日期要是字符串,赶紧转。
  3. 然后 info() —— 定位缺失值。哪些列缺了多少,心里有数。
  4. 接着 describe() —— 发现异常值。负金额、超大值、离谱的均值,都在这步暴露。
  5. 最后 head() + sample() —— 肉眼验证一下。看看数据长什么样,有没有明显的格式问题。
# 我的标准流程
def data_audit(df):
    print("="*50)
    print("1. 数据形状:", df.shape)
    print("="*50)
    print("\n2. 字段类型:")
    print(df.dtypes)
    print("\n3. 数据信息:")
    df.info()
    print("\n4. 数值统计:")
    print(df.describe())
    print("\n5. 前5行预览:")
    print(df.head())
    print("\n6. 随机抽样:")
    print(df.sample(5))

我的习惯:把这个函数保存成脚本,每次拿到新数据先跑一遍。5秒钟就能知道数据健不健康。省下的时间,够你喝杯咖啡了。

说白了,数据剖析不是为了炫技,而是为了少走弯路。你想想看,如果连数据有多少缺失、类型对不对都不知道,就开始写清洗代码,那不是盲人摸象吗?

所以,拿到数据别急着动手。先体检,再开刀。这是数据工程师的基本素养。


专注资料整理