摘要
拿到一份数据后,不应该马上开始清洗、分组或建模。第一步应先认识数据集:有多少行、多少列、字段含义是什么、数据类型是否正确、缺失值分布如何、数值范围是否异常、分类字段有哪些取值。
本文围绕 pandas 的数据概览能力,介绍head、info、describe、shape、dtypes、isna、value_counts、nunique等常用方法,并通过一份订单数据示例,建立一套拿到数据后的探索检查流程。
一、背景与问题
很多数据分析错误不是出现在复杂算法,而是出现在最开始的数据理解阶段:
- 日期字段被当成字符串处理。
- 金额字段混入了空值、字符或异常负数。
- 分类字段存在大小写、空格和别名问题。
- 主键并不唯一,导致合并后数据量膨胀。
- 缺失值集中在某些业务状态中,被误认为随机缺失。
- 统计指标直接基于脏数据计算,导致结论偏差。
因此,数据分析的第一步不是“算结果”,而是回答几个基础问题:
这份数据有多大? 每一列是什么含义? 类型是否符合业务预期? 有没有缺失、重复和异常? 关键字段的分布是否合理? 是否可以支撑后续分析目标?数据概览就是在正式处理前建立对数据的第一层认知。
二、核心概念
1. 数据规模
数据规模包括行数、列数、内存占用和字段数量。pandas 中常用:
| 方法 | 作用 |
|---|---|
df.shape | 查看行数和列数 |
df.columns | 查看列名 |
df.info() | 查看非空数量、类型和内存 |
df.memory_usage() | 查看内存占用 |
规模决定了后续处理方式。几千行数据可以直接交互式分析,几千万行数据则需要分块、数据库或更高性能工具。
2. 字段类型
字段类型决定能否进行正确计算:
- 金额和数量应是数值类型。
- 日期应转换为日期时间类型。
- 状态、地区、渠道适合作为分类字段。
- ID 字段通常应作为字符串处理,而不是数值。
ID 如果被当作数字,可能丢失前导零,例如订单号000123变成123。
3. 缺失值
缺失值并不一定是错误。它可能表示:
- 业务上尚未发生。
- 数据采集失败。
- 用户未填写。
- 某些类型的记录没有该字段。
- 系统迁移导致历史数据不完整。
处理缺失值前,必须先理解缺失原因。
4. 分布与异常
数据分布帮助判断字段是否合理。例如:
- 金额是否出现负数。
- 年龄是否超过合理范围。
- 状态字段是否出现未知值。
- 日期是否超出分析窗口。
- 某个渠道是否占比异常高。
探索阶段不一定立即修复问题,但要记录所有可疑点。
三、工作原理
1. 数据探索流程
一套通用流程如下:
读取数据 → 查看样例行 → 检查规模和列名 → 检查数据类型 → 检查缺失值 → 检查重复值 → 检查数值分布 → 检查分类字段取值 → 记录数据问题探索流程的目标不是把所有问题一次性解决,而是形成数据画像。
2. 样例行的价值
head()和tail()可以快速观察数据格式,但不要只看前几行就下结论。很多数据文件前几行可能是特殊样本,例如测试数据、历史数据或导出说明。
可以随机抽样查看:
df.sample(5,random_state=42)随机样本更容易暴露字段格式不一致的问题。
3. 统计描述的边界
describe()对数值列非常有用,但它只能提供基础统计。平均值、最大值和最小值不能替代业务判断。例如订单金额最大值很大,可能是大客户订单,也可能是金额单位错误。
4. 探索结果应可复用
数据探索不应只停留在 Notebook 输出中。可以将关键检查封装为函数,形成每次读取数据后的固定检查流程。
四、实战示例
1. 准备示例数据
frompathlibimportPathimportpandasaspd data_dir=Path("data")data_dir.mkdir(exist_ok=True)orders=pd.DataFrame({"order_id":["A001","A002","A003","A004","A004","A006"],"customer":["Alice","Bob","Carol","David","David",None],"region":["华东","华南","华东","华北","华北","华东 "],"amount":[1200.0,800.0,1560.0,-20.0,-20.0,None],"status":["paid","pending","paid","cancelled","cancelled","Paid"],"order_date":["2026-09-01","2026-09-02","2026-09-03","2026-09-04","2026-09-04","bad-date",],})orders.to_csv(data_dir/"orders.csv",index=False,encoding="utf-8-sig")这份数据故意包含重复订单、缺失客户、负金额、状态大小写不一致、地区空格和错误日期。
2. 读取数据并查看样例
importpandasaspd df=pd.read_csv("data/orders.csv")print(df.head())print(df.tail())print(df.sample(3,random_state=42))样例查看主要用于确认列名、字段内容和明显格式问题。
3. 查看规模和字段
print("shape:",df.shape)print("columns:",df.columns.tolist())print(df.info())info()中的非空数量可以快速判断哪些列存在缺失。对象类型列需要继续判断是字符串、混合类型还是日期未转换。
4. 检查数据类型
print(df.dtypes)df["amount"]=pd.to_numeric(df["amount"],errors="coerce")df["order_date"]=pd.to_datetime(df["order_date"],errors="coerce")print(df.dtypes)转换后应重新检查缺失值,因为无法解析的数据会被转换为缺失。
5. 缺失值分析
missing_count=df.isna().sum()missing_rate=df.isna().mean().sort_values(ascending=False)print(missing_count)print(missing_rate)缺失率高的字段不一定要删除,先判断它是否对当前分析目标关键。
6. 重复值检查
print("duplicated rows:",df.duplicated().sum())print("duplicated order_id:",df["order_id"].duplicated().sum())print(df.loc[df["order_id"].duplicated(keep=False)])整行重复和业务主键重复是两类不同问题。主键重复可能意味着重复导出、拆单、退款记录或数据错误。
7. 数值字段概览
print(df["amount"].describe())print(df.loc[df["amount"]<0,["order_id","amount","status"]])负金额可能是退款,也可能是错误录入。探索阶段应把它标记出来,后续根据业务规则处理。
8. 分类字段分布
print(df["status"].value_counts(dropna=False))print(df["region"].value_counts(dropna=False))状态字段中paid和Paid可能表示同一个含义,地区字段中的华东和华东也可能因为空格被当成不同值。
9. 字符串标准化预览
preview=df.copy()preview["status_clean"]=preview["status"].str.strip().str.lower()preview["region_clean"]=preview["region"].str.strip()print(preview["status_clean"].value_counts(dropna=False))print(preview["region_clean"].value_counts(dropna=False))先做预览,不急着覆盖原字段。确认规则正确后,再进入正式清洗阶段。
10. 封装探索函数
defprofile_dataframe(frame:pd.DataFrame)->dict:return{"shape":frame.shape,"columns":frame.columns.tolist(),"dtypes":frame.dtypes.astype(str).to_dict(),"missing_count":frame.isna().sum().to_dict(),"missing_rate":frame.isna().mean().round(4).to_dict(),"duplicated_rows":int(frame.duplicated().sum()),}profile=profile_dataframe(df)print(profile)封装后可以对不同数据文件重复使用,也可以输出为 JSON 或 Markdown 报告。
11. 输出数据概览报告
frompathlibimportPath output_dir=Path("output")output_dir.mkdir(exist_ok=True)summary=pd.DataFrame({"dtype":df.dtypes.astype(str),"missing_count":df.isna().sum(),"missing_rate":df.isna().mean(),"unique_count":df.nunique(dropna=True),})summary.to_csv(output_dir/"data_profile.csv",encoding="utf-8-sig")print(summary)这种字段级报告适合放进数据交付流程,用于和业务同学确认字段质量。
五、常见问题与实践建议
1. 为什么不能只看head()?
前几行可能恰好很干净,不能代表整体。建议结合sample()、缺失值统计、分类分布和数值描述一起判断。
2.describe()是否能发现所有异常?
不能。它只能帮助发现明显的数值极端值。分类值拼写错误、日期解析失败、主键重复、业务状态非法,需要单独检查。
3. 缺失值是否应该全部填 0?
不应该。0 是一个有意义的数值,缺失表示未知或不存在。把缺失值填 0 可能改变统计结果。应根据字段语义决定填充、删除、保留或单独标记。
4. 为什么 ID 字段建议读成字符串?
ID 可能包含前导零、字母、连接符或超长数字。读成数值可能导致格式丢失或精度问题。订单号、手机号、身份证号等通常都应该按字符串处理。
5. 探索阶段要不要直接修改数据?
建议先生成问题清单和预览结果,再进入正式清洗。探索和清洗分开,可以减少误修改,也便于复盘每条规则的原因。
六、进阶思考
1. 建立数据字典
数据字典至少包含:
| 字段 | 内容 |
|---|---|
| 字段名 | 数据文件中的列名 |
| 中文含义 | 字段业务解释 |
| 数据类型 | 字符串、数值、日期等 |
| 是否必填 | 是否允许缺失 |
| 取值范围 | 合法值或范围 |
| 示例 | 典型样例 |
没有数据字典时,分析人员容易依靠猜测解释字段。
2. 用规则沉淀数据质量检查
探索阶段发现的问题,可以逐步变成数据质量规则:
order_id 不允许为空 order_id 在订单主表中应唯一 amount 不允许为空 amount 允许为负数时必须对应退款状态 order_date 必须能解析为日期 status 必须属于预定义枚举这些规则后续可以用测试或数据质量工具自动执行。
3. 从探索到自动化
手工探索适合新数据集。稳定数据源应逐步自动化:
数据读取 → 字段检查 → 类型检查 → 质量规则 → 输出概览报告 → 进入清洗流程这样每次数据更新后都能快速发现异常。
4. 注意样本偏差
如果数据来自抽样、筛选或某个时间窗口,概览结果只代表当前样本。报告中应记录数据范围、抽样方式和数据来源。
结论
认识数据集是数据分析的第一步。通过 pandas 的shape、info、dtypes、isna、describe、value_counts、nunique等方法,可以快速建立数据画像,发现缺失、重复、类型错误和异常分布。
下一篇将进入数据读取实践,系统讲解 CSV、Excel 和数据库数据如何读入 pandas,并处理编码、日期、类型和大文件问题。
参考资料
- pandas 官方文档:https://pandas.pydata.org/docs/
- pandas
DataFrame.info:https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.info.html - pandas
DataFrame.describe:https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.describe.html