Python清洗CSV缺失值教程:填充或删除空值
用pandas处理CSV中的缺失值,包括删除空行、用均值/中位数/众数填充、前向填充、标记缺失列,附完整可运行代码。
场景痛点
导出的CSV总有空单元格:有的用户没填年龄、有的订单缺金额、有的整行是空行。直接拿去做统计,均值算不对、分组报错、画图直接崩。用pandas先把缺失值处理干净:能填的填,该删的删,干净了再分析。
用到的库
pip install pandas
完整代码
# 清洗CSV缺失值
import pandas as pd
import numpy as np
def inspect_missing(df):
"""先看一眼每列缺了多少。"""
total = len(df)
missing = df.isna().sum()
ratio = (missing / total * 100).round(1)
report = pd.DataFrame({"缺失数": missing, "缺失占比%": ratio})
print(report[report["缺失数"] > 0])
return report
def drop_empty_rows(df):
"""
删整行全为空的行。
how="all" 表示整行全NaN才删;how="any" 是任意一个NaN就删。
"""
before = len(df)
df_clean = df.dropna(how="all")
after = len(df_clean)
print(f"删除全空行:{before} -> {after}")
return df_clean
def fill_missing(df):
"""
按列策略填充缺失值:
- 数值列:用中位数填(比均值抗异常值)
- 文本列:用"未知"填
- 时间列:前向填充ffill(按时间顺序上一个有效值)
"""
df = df.copy()
for col in df.columns:
if df[col].dtype in [np.float64, np.int64, "Int64", "Float64"]:
# 数值列用中位数填
median_val = df[col].median()
df[col] = df[col].fillna(median_val)
print(f" {col} 用中位数 {median_val} 填充")
else:
# 文本列用"未知"
df[col] = df[col].fillna("未知")
print(f" {col} 用'未知'填充")
return df
def fill_by_group(df, group_col, value_col):
"""
更精细:按分组填,比如按城市分组,用该城市的平均年龄填缺失。
"""
df[value_col] = df.groupby(group_col)[value_col].transform(
lambda s: s.fillna(s.median())
)
print(f"按 {group_col} 分组填充 {value_col} 完成")
return df
def main():
input_file = "messy_data.csv"
df = pd.read_csv(input_file, encoding="utf-8-sig")
print("=== 1. 缺失值体检 ===")
inspect_missing(df)
print("\n=== 2. 删全空行 ===")
df = drop_empty_rows(df)
print("\n=== 3. 按列策略填充 ===")
df = fill_missing(df)
# 分组填充示例
# df = fill_by_group(df, "城市", "年龄")
# 最终导出
df.to_csv("cleaned_data.csv", index=False, encoding="utf-8-sig")
print(f"\n清洗完成,导出 cleaned_data.csv,{len(df)} 行")
if __name__ == "__main__":
main()
代码讲解
df.isna().sum()统计每列缺失数,先体检再决定怎么处理。dropna(how="all")只删整行全空的,how="any"太激进,别乱用。- 数值列用中位数填充,比均值抗异常值(比如收入有个亿万富翁不影响中位数)。
- 文本列填"未知",保留这条记录,不要直接删。
groupby.transform按组填充,比全局填充更贴合业务实际。- 清洗前后都
len(df)对比,心里清楚删了多少。
运行结果
控制台先打印缺失值报告,显示每列缺多少、占比多少;然后逐列说明填充策略;最后生成 cleaned_data.csv,所有空单元格都填好了,没有空行。
注意事项
- 缺失超过80%的列建议直接删掉,填充也是噪音,
df.drop(columns=[]). - 时间序列数据用
ffill()(上一个值)或bfill()(下一个值)比填均值合理。 - 填充会改变数据分布,重要分析前记录一下填充比例和策略,方便复现。
- 空字符串
""和NaN不是一回事,先df.replace("", np.nan)统一。 - 关键列(比如主键)缺失的行直接删,别填,填了就对不上了。

更新时间:2026-09-14 21:02:40
上一篇:Python CSV转JSON教程:表格导出为接口格式