问题与目标
真实表格常包含缺失值、重复记录、错误类型和分散在多张表中的字段。Pandas 用 Series 和 DataFrame 表达带标签的一维与二维数据,并提供清洗、连接、分组和时间处理工具。
完成标准:能检查数据质量,按业务规则处理缺失和重复,合并两张表,完成分组聚合与按月统计。本篇不追求覆盖全部 DataFrame API。

清洗不是一条 dropna() 语句,而是类型校正、缺失处理、去重、关联和质量复查组成的链路。每一步都应说明规则,并能追踪表格行数和字段状态的变化。
核心概念
DataFrame 的列名和索引都是标签。选择列优先 df["column"],按标签选择使用 .loc,按位置使用 .iloc。布尔条件组合必须加括号并使用 &、|,不能写 Python 的 and、or。
缺失值处理不是固定执行 dropna():先统计缺失位置,再判断删除、填充、保留还是回查源数据。merge 要明确连接键和连接方式,并验证连接前后的行数,防止重复键造成行数膨胀。
groupby 遵循“拆分—计算—合并”。日期先通过 to_datetime 转换,随后才能用 .dt 或时间索引重采样。
读取边界先固定数据契约
数据契约至少包括列名、类型、是否可空、唯一键、单位和取值范围。读取 CSV 时应优先控制类型,而不是让自动推断决定标识符:
import pandas as pd
sample = pd.DataFrame({
"task_id": ["001", "002"],
"duration": [12.5, 18.0],
})
sample.to_csv("tasks.csv", index=False)
loaded = pd.read_csv("tasks.csv", dtype={"task_id": "string"})
print(loaded.dtypes)
真实文件还要确认编码、分隔符、小数点和日期时区。读取后立即记录 shape、列名、类型、重复键和缺失数量,形成清洗前快照。
缺失值需要业务规则
缺失可能表示未采集、不适用、系统故障或真实的“没有”。删除、均值填充、中位数填充和分组填充会引入不同偏差。应把原始缺失标记保留下来,必要时增加 was_missing 特征。
frame = pd.DataFrame({"group": ["A", "A", "B"], "value": [10.0, None, 80.0]})
frame["value_was_missing"] = frame["value"].isna()
frame["value"] = frame["value"].fillna(
frame.groupby("group")["value"].transform("median")
)
print(frame)
若某组全部缺失,分组中位数仍是缺失,需要明确备用规则。
合并前后验证关系
merge(validate="many_to_one") 能检查右表键唯一。还可使用 indicator=True 查看哪些键只在左表或右表,避免连接失败被静默变成空值。合并前后至少核对行数、主键唯一性和关键字段缺失量。
可运行实现
python -m pip install pandas
import pandas as pd
sales = pd.DataFrame(
{
"order_id": [1, 2, 2, 3, 4],
"region_id": [10, 10, 10, 20, 20],
"date": ["2026-01-05", "2026-01-20", "2026-01-20", "bad", "2026-02-02"],
"amount": [120.0, None, None, 300.0, 180.0],
}
)
regions = pd.DataFrame(
{"region_id": [10, 20], "region": ["north", "south"]}
)
sales = sales.drop_duplicates(subset="order_id").copy()
sales["date"] = pd.to_datetime(sales["date"], errors="coerce")
sales["amount"] = sales["amount"].fillna(sales["amount"].median())
clean = sales.dropna(subset=["date"])
merged = clean.merge(regions, on="region_id", how="left", validate="many_to_one")
summary = (
merged.groupby("region", as_index=False)
.agg(order_count=("order_id", "count"), total_amount=("amount", "sum"))
)
monthly = merged.set_index("date")["amount"].resample("MS").sum()
print(summary)
print(monthly)
输入有重复 ID、缺失金额和非法日期。输出只保留合法订单,用全局中位数填充金额,关联地区后统计订单数、总金额和月度金额。
读取外部数据后先做结构检查:
data = pd.read_csv("sales.csv", dtype={"region_id": "string"})
print(data.shape)
print(data.dtypes)
print(data.head())
print(data.isna().sum())
编码、分隔符和列类型应在读取边界尽早处理;标识符即使全是数字,也可能更适合作为字符串。
分组、转换与透视
agg 折叠每组,transform 返回与原表等长结果,filter 按组保留或删除。透视表适合把多个类别维度组织成行列,但需要明确重复组合使用何种聚合函数。
时间序列重采样前应设置时间索引并排序。MS 表示月初频率;缺失月份是否补 0 取决于“没有记录”是否真的等于“指标为 0”。
进一步验证
- 为订单表增加重复 ID、空地区和带时区的日期,记录每条规则影响的行数。
- 故意在地区维表中放入重复键,使用
validate="many_to_one"暴露错误。 - 分别用
agg、transform计算地区均值,核对输出行数为何不同。 - 将清洗前后的行数、缺失数和主键唯一性整理成质量报告。
检查结果应能追溯某一行为什么被保留、修复或剔除,同时确保原始文件不被覆盖。
常见问题与排查
- 链式赋值警告:筛选后
.copy(),再通过.loc明确赋值。 - 合并后行数突然增加:连接键在右表不唯一,使用
validate暴露关系错误。 - 缺失值全部删除:可能改变样本分布;记录处理规则和处理前后行数。
- 日期解析结果大量
NaT:抽取失败样本,检查格式、时区和日月顺序。 - 对每行使用
apply(axis=1):优先列运算、映射和向量化条件。
小结
Pandas 的主线是先确认表结构和数据质量,再执行转换、连接与聚合。每一步都记录行数、缺失量和键唯一性,分析结果才具备可追溯性。
License: CC BY-NC 4.0
Updated 2 hours ago
Was this article helpful? Give it a like.
0 comments


