尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Pandas数据清洗实战:缺失值、重复值与类型转换全攻略

Pandas数据清洗实战:缺失值、重复值与类型转换全攻略 这次我们来看一套 Pandas 数据清洗的完整实战方法。如果你手里正好有一批“不太干净”的原始数据有空值、有重复行、格式乱、类型不对、日期没法排序、文本里带空格和怪符号那么这篇文章可以直接收藏。Pandas 是 Python 数据分析生态里最核心的表格处理库它最擅长的就是把脏数据“收拾”成能直接用于分析、建模、报表的结构化数据。本文会从环境准备、数据加载、缺失值处理、重复值去除、类型转换、文本清洗、时间标准化一直写到批量任务和性能优化全程带示例代码你可以照着自己的数据替换路径直接跑。做数据处理的人都知道一句话分析 80% 的时间花在清洗数据上只有 20% 花在建模和可视化上。这句话听起来有点夸张但真实项目里确实如此。Pandas 之所以能成为数据清洗的默认工具核心是它把“表格”操作变成了几行代码能完成的事情按条件筛行、按列计算、分组聚合、拼接合并、透视变形全部有现成接口。你不需要写一堆 for 循环去逐行处理只要明确清洗逻辑然后用对应的 DataFrame 方法一次性完成。这篇文章会重点演示几个高频场景缺失值修复、重复数据去重、类型错误修复、文本脏数据规范化、日期字段统一以及如何把清洗结果导出成结构化文件。最后还会给出一套批量清洗多个文件的工程化模板。老规矩先给一张能力速览表方便你快速判断这套方法适不适合自己的场景。1. 核心能力速览能力项说明工具类型Python 第三方数据分析库核心功能数据加载、缺失值处理、去重、类型转换、文本清洗、时间解析、聚合统计、批量处理语言环境Python 3.8 及以上安装方式pip 安装无需编译运行方式脚本文件、Jupyter Notebook、命令行均可操作系统Windows / macOS / Linux 均可主要数据源CSV、Excel、JSON、SQL 数据库、Parquet、Feather输出格式CSV、Excel、JSON、Parquet、Feather、数据库表是否支持批量任务支持可通过脚本遍历目录批量处理是否支持接口 API本身不是 Web 服务但可通过 FastAPI / Flask 包装成接口适合场景数据清洗、特征工程、数据分析、报表生成、结构化数据建模准备Pandas 不挑硬件普通办公电脑就能跑。数据集在几千万行以内用 Pandas 都很顺手再往上就要考虑分块读取或者换 PySpark 那套方案了。下面我们从环境准备开始逐步走完整套清洗流程。每一节我都会给你可运行的代码你只需要把文件路径换成自己的数据路径即可。2. 适用场景与使用边界先明确这套流程适合解决什么问题。第一类是“格式不统一”的数据比如日期字段有的写成2024-01-01有的写成2024/1/1还有的写成20240101不统一就没法排序、没法聚合。第二类是“缺失值”数据比如用户注册表里手机号为空、购物订单表里金额缺失这些空值会影响统计结果和模型训练。第三类是“重复数据”比如同一个订单被导出了两遍或者同一用户在一张表里出现多次不删除重复项就直接汇总指标一定是错的。第四类是“类型错误”的数据比如数字被读成了字符串金额列用object类型存着求和的时候直接报错或者结果是拼接字符串。第五类是“文本脏数据”比如姓名前后带空格、产品名称里混入全角半角符号、分类字段大小写不一致。Pandas 对这些问题都有非常成熟的解决方案。但也要说清楚边界Pandas 适合规则明确的清洗任务如果你要处理的是无规则的长文本、需要理解语义的数据比如判断一段评论是好评还是差评那就不是 Pandas 的主场应该交给 NLP 或者大模型去处理。另外Pandas 会把数据加载到内存中处理如果你的单表文件超过内存容量或者需要做分布式计算那就要考虑换用 Spark、Dask 或者数据库方案。还有一个容易被忽视的点数据清洗涉及隐私和版权边界。如果你处理的表里有手机号、身份证号、银行卡号这些敏感字段清洗后要及时脱敏。如果数据来自第三方要确认你是否有权处理、分析和发布。批量化处理业务数据时建议先在小样本上验证清洗规则确认无误后再全量跑避免一条错误规则把几百万行数据改坏。3. 环境准备与前置条件Pandas 是第三方库需要先安装到 Python 环境里。检查你的电脑上是否有 Python打开终端或命令行执行python --version如果没有安装 Python去 Python 官网下载对应系统的最新稳定版。安装过程中勾选“Add Python to PATH”这样可以在命令行里直接使用 Python。如果已经有 Python 环境接着安装 Pandaspip install pandas如果你的网络环境使用国内镜像更快可以用清华源安装pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后验证版本python -c import pandas as pd; print(pd.__version__)能输出版本号说明 Pandas 安装成功。如果后面还要做 Excel 文件读写建议一起安装 openpyxlpip install openpyxl写代码的时候建议使用 VS Code 或者 Jupyter Notebook。VS Code 的 Python 插件用起来比较方便Jupyter Notebook 则适合一边写代码一边看中间结果尤其在数据清洗阶段你可以分格逐步查看每一步处理后的效果。4. 数据加载与初步探查先创建一份示例数据模拟一个真实的“脏数据”场景。我们手动造一张 CSV 表格里面包含缺失值、重复行、类型错乱、日期格式不统一、文本中有空格等典型问题。下面这段代码会生成一份raw_data.csv文件import pandas as pd data [ {order_id: 1001, user_name: 张三 , amount: 128.5, status: 已完成, order_date: 2024-01-05}, {order_id: 1002, user_name: 李四, amount: 89, status: 待付款, order_date: 2024/1/6}, {order_id: 1003, user_name: 王五, amount: None, status: 已完成, order_date: 20240107}, {order_id: 1001, user_name: 张三, amount: 128.5, status: 已完成, order_date: 2024-01-05}, {order_id: 1004, user_name: 赵六, amount: 256.75, status: 已退款, order_date: 2024-01-08}, {order_id: 1005, user_name: 孙七, amount: abc, status: 已完成, order_date: 2024/01/09}, {order_id: 1006, user_name: 周八, amount: 45, status: 已完成, order_date: 2024-01-10}, ] df pd.DataFrame(data) df.to_csv(raw_data.csv, indexFalse, encodingutf-8-sig) print(示例数据已生成)加载数据用pd.read_csv()import pandas as pd df pd.read_csv(raw_data.csv) print(df) print(数据形状, df.shape)输出之后你会看到明显的脏数据问题order_id有重复user_name里的“张三”前后带空格amount字段既有缺失值又有字符串abcorder_date有三种完全不同的日期格式数据行里还有完全重复的记录。先不用着急处理第一步是系统性地探查数据质量。下面这些方法是最常用的数据体检手段# 查看数据基本信息 print(df.info()) # 查看每列缺失值数量 print(df.isnull().sum()) # 查看数值列的统计描述 print(df.describe()) # 查看重复行 print(重复行数量, df.duplicated().sum())df.info()会告诉我们每列的数据类型、非空值个数。正常情况下amount应该是 float 或 int但在我们的示例里它是object说明数字被读成了字符串后面需要转换。df.isnull().sum()直接告诉我们哪些列有多少个空值这是后续缺失值处理的起点。df.duplicated().sum()则告诉我们重复行数量。5. 缺失值处理与修复缺失值是最常见的数据质量问题。处理缺失值有几种常见思路直接删除、填充固定值、填充统计值、向前/向后填充、根据其他列计算填充。具体用哪种取决于业务含义。5.1 查看缺失值分布先精确定位哪些行列存在缺失值# 查看哪些行有空值 print(df[df.isnull().any(axis1)])这里axis1表示按行检查只要有任意一列为空该行就会被筛出来。如果是大表可以只查看前几行定位问题print(df[df.isnull().any(axis1)].head(10))5.2 删除缺失值如果缺失值占整体比例很小且缺失字段不影响分析可以直接删除所在行df_clean df.dropna() print(删除缺失值后形状, df_clean.shape)dropna()默认删掉包含任何缺失值的行。如果只想在指定列上检查缺失值比如只要amount为空就删除df_clean df.dropna(subset[amount])5.3 填充缺失值如果缺失值不能删就用填充。填充逻辑要看业务金额缺失可以填充 0 或均值分类字段缺失可以填充“未知”时间序列数据根据时间顺序向前填充。# amount 缺失填充 0 df[amount] df[amount].fillna(0) # 分类字段填充未知 df[status] df[status].fillna(未知) # 数值列填充均值 df[amount] df[amount].fillna(df[amount].mean())也可以使用分组填充按用户分组组内用用户自己的均值填充缺失金额。这在用户行为数据里比较常见。df[amount] df.groupby(user_name)[amount].transform(lambda x: x.fillna(x.mean()))5.4 用前值或后值填充时间序列数据适合用ffill用上一个有效值填充或bfill用下一个有效值填充df[amount] df[amount].ffill() df[amount] df[amount].bfill()注意填充策略不能盲目套用。均值填充适合分布比较均匀的数值列但会拉低方差前值填充适合时间序列但如果你没按时间排序填充结果就是错的。做缺失值处理之前先想清楚业务含义再选择对应策略。6. 重复数据清洗重复数据会导致统计结果虚高。根据业务场景有两种重复完全重复的行以及基于指定列判断的重复记录。完全重复可以直接删除指定列重复则需要确认保留哪一条。6.1 检查重复行# 查看重复行 print(df[df.duplicated()])此时示例数据里的第三行和第一行内容相同属于完全重复行。6.2 删除完全重复行df df.drop_duplicates() print(删除完全重复行后形状, df.shape)drop_duplicates()默认保留第一次出现的记录删除后续出现的重复行。6.3 按指定列去重并保留第一条业务里更常见的情况是同一用户出现多次我们只保留一条或者同一个订单 ID 出现多次需要保留最早或最新的一条。比如热搜词里提到的“pandas如果指定两列的值均相同则取第一条数据即可”这正是按多列联合去重的场景# 如果 order_id 和 user_name 两列值均相同则保留第一条 df df.drop_duplicates(subset[order_id, user_name], keepfirst)keep参数有三个可选值first保留第一次出现的记录last保留最后一次出现的记录False则删除所有重复记录。如果业务要求保留最新订单可以按日期排序后再处理# 先按订单日期排序再按用户去重保留最新一条 df df.sort_values(order_date, ascendingFalse) df df.drop_duplicates(subset[user_name], keepfirst)这里有个执行顺序问题sort_values必须在drop_duplicates之前否则去重时无法按照“最新”逻辑保留。建议在代码注释里写清楚这一步的意图方便后续他人维护。7. 数据类型转换与结构化数据建模准备数据加载进来之后类型不对会导致大量后续问题。比如金额列是object排序会变成字符串排序求和会直接报错。Pandas 里最常用的类型转换方法是to_numeric()和astype()。7.1 数值类型转换对于示例数据里的amount列里面有128.5这样的数字字符串还有abc这样的非法值。直接用astype(float)会报错所以要用to_numeric加errors参数# 把 amount 列转为数值类型无法转换的置为 NaN df[amount] pd.to_numeric(df[amount], errorscoerce)errorscoerce表示“遇到无法解析的值就变成 NaN”。这样abc会被转成 NaN后续再用缺失值处理逻辑修复。如果你想在转换失败时看到具体原因可以先定位异常值mask pd.to_numeric(df[amount], errorscoerce).isna() df[amount].notna() print(df[mask])这样就能排查出原始数据里到底哪些值是非法的。7.2 字符串类型转换对于不需要数值计算的列可以统一转成字符串类型df[user_name] df[user_name].astype(str)如果某些单元格是数字类型而业务上需要按文本处理这一步就很有必要。7.3 布尔类型转换如果某列只有“是/否”或“0/1”两种值可以转成布尔类型便于后续条件筛选df[is_valid] df[status].map({已完成: True, 待付款: False, 已退款: False})7.4 结构化建模的数据类型要求做结构化数据建模之前数据类型必须精确匹配算法要求。机器学习库通常不接受字符串类型的特征所以分类变量要转成数值编码日期列要转成时间类型目标列要转成 0/1 或数值标签。以下是一个典型的建模前数据处理流程# 金额字段转数值 df[amount] pd.to_numeric(df[amount], errorscoerce) # 日期字段转时间类型 df[order_date] pd.to_datetime(df[order_date]) # 分类字段转 category 类型降低内存占用 df[status] df[status].astype(category) # 分类字段转数值编码 df[status_code] df[status].cat.codescategory类型对内存友好尤其适合重复度高的分类字段。在数据量大、内存吃紧的场景下把字符串列转成category能明显降低内存占用。8. 文本脏数据规范化文本列里的脏数据一般表现为前后空格、全角半角混用、大小写不一致、不可见字符、特殊符号。这些内容肉眼很难完全发现所以要用 Pandas 的字符串方法统一清洗。Pandas 里所有字符串操作都通过.str访问器调用。8.1 去除首尾空格和指定字符df[user_name] df[user_name].str.strip()strip()去除首尾空格。如果需要去除特定字符比如数字前后的引号df[user_name] df[user_name].str.strip(\)8.2 去除中间多余空格姓名或文本中间如果有多个连续空格可以用正则替换df[user_name] df[user_name].str.replace(r\s, , regexTrue)\s表示一个或多个空白字符替换成单个空格。如果要去掉所有空格直接把替换值改为空字符串df[user_name] df[user_name].str.replace(r\s, , regexTrue)8.3 大小写统一姓名、国家、城市这类文本字段经常出现大小写不统一的问题# 全部转小写 df[status] df[status].str.lower() # 全部转大写 df[status] df[status].str.upper() # 转换为驼峰格式 df[user_name] df[user_name].str.title()8.4 全角转半角中文输入法经常把字母和数字打成全角比如和128看起来差不多但程序会认为是不同的字符串。全角转半角是一个很实用的清洗步骤def full_to_half(text): if not isinstance(text, str): return text result [] for char in text: code ord(char) if code 0x3000: code 0x20 elif 0xFF01 code 0xFF5E: code - 0xFEE0 result.append(chr(code)) return .join(result) df[user_name] df[user_name].apply(full_to_half)8.5 替换和删除非法字符有时候文本里混入换行符、制表符、零宽空格这些会导致导出数据在可视化或数据库中显示异常# 去掉换行符和制表符 df[status] df[status].str.replace(r[\r\n\t], , regexTrue) # 去掉所有非中文、非字母、非数字、非常用标点的字符 df[user_name] df[user_name].str.replace(r[^\w\u4e00-\u9fff\u3000-\u303f\uff00-\uffef。、], , regexTrue)上面的正则表达式保留中文、字母、数字以及常见中文标点其他字符全部删除。正则表达式清洗时建议先在单独一列上测试确认不会误删有效信息后再应用到全表。8.6 文本条件替换脏数据里经常有同一含义的不同写法比如“已完成”“完成”“已结束”都表示同一个业务状态。可以用replace将多种取值统一成一个标准值df[status] df[status].replace({ 已完成: 完成, 完成: 完成, 已结束: 完成, 待付款: 待支付, })这种映射方式比显式赋值更清晰所有规则都写在一个字典里方便后续修改和维护。9. 日期时间数据标准化日期格式不统一是最让人头疼的问题之一。Pandas 的to_datetime()能自动解析大多数常见日期格式包括2024-01-05、2024/1/6、20240107这种字符串。默认情况下它会自动推断格式df[order_date] pd.to_datetime(df[order_date]) print(df[order_date].dtype)输出应该是datetime64[ns]这样日期列就能直接排序、按年月筛选也能做时间序列分析。但要注意to_datetime()自动解析并不总是成功的遇到混合格式或非法日期时可以指定format参数df[order_date] pd.to_datetime(df[order_date], format%Y/%m/%d, errorscoerce)errorscoerce的作用和数值转换一样解析失败置为 NaN。日期标准化之后可以从中提取年、月、日、周、季度等特征这是结构化数据建模时常用的特征工程操作df[year] df[order_date].dt.year df[month] df[order_date].dt.month df[day] df[order_date].dt.day df[weekday] df[order_date].dt.weekday df[quarter] df[order_date].dt.quarter时间数据里还有一个高频场景时间戳是object字符串需要转成时间类型再计算时间差。比如两个日期列的间隔天数df[diff_days] (df[order_date] - pd.to_datetime(df[another_date])).dt.days日期处理容易踩的坑有三个一是errors参数没设置遇到非法日期直接抛异常二是没有统一时区不同来源的数据可能带08:00等时区标识先统一转成UTC再处理三是 Excel 里读出的日期是浮点数需要先用pd.to_datetime(origin1899-12-30, unitD)做处理。10. 数据输出与存储格式选择清洗完成后数据需要导出为结构化文件。最常见的是 CSV但 CSV 有编码问题、类型丢失问题如果后续还要被其他程序继续处理推荐使用 Parquet 或 Feather 这类高效列式存储格式。10.1 导出 CSVdf.to_csv(clean_data.csv, indexFalse, encodingutf-8-sig)indexFalse表示不额外保存行索引。encodingutf-8-sig是为了让 Excel 打开 CSV 时中文不乱码。如果你做的是金融数据处理或数据交换建议保留英文编码标准df.to_csv(clean_data.csv, indexFalse, encodingutf-8)10.2 导出 Exceldf.to_excel(clean_data.xlsx, indexFalse, sheet_name清洗结果)10.3 导出 Parquet 和 FeatherParquet 和 Feather 是列式存储格式读写速度快保留数据类型而且压缩率更高。数据从清洗到建模如果中间链路很长建议用这两种格式保存中间结果# 需要安装 pyarrow # pip install pyarrow df.to_parquet(clean_data.parquet, indexFalse) df.to_feather(clean_data.feather)读取也很简单df pd.read_parquet(clean_data.parquet) df pd.read_feather(clean_data.feather)Parquet 的优势是兼容 Spark、Hive 等大数据组件Feather 的优势是读写速度极快适合单个机器上的快速中间缓存。如果你的数据后续要进入 Spark 环境做分布式处理用 Parquet 是最稳妥的选择。这也是很多人提到的“pandas 与 numpy 去对接 parquet、feather 等格式”的实际用法。10.4 导出到 SQLite 数据库数据量大或者需要频繁查询时可以写入 SQLite 数据库import sqlite3 conn sqlite3.connect(clean_data.db) df.to_sql(orders, conn, if_existsreplace, indexFalse) conn.close()之后可以用 SQL 直接查询不需要反复读取 CSV 文件。if_existsreplace表示表如果存在就覆盖。如果你不希望覆盖原有数据可以改成append。11. 批量任务与工程化清洗流程真实业务里你不会只有一张表而是一批文件每日导出的订单、每周汇总的用户表、不同子系统导出的原始数据。这时候写一个批量清洗的 Python 脚本就很有必要。11.1 批量读取目录下的所有 CSV 文件import pandas as pd from pathlib import Path input_dir Path(./raw_data) output_dir Path(./clean_data) output_dir.mkdir(exist_okTrue) csv_files list(input_dir.glob(*.csv)) print(找到文件数量, len(csv_files)) for csv_file in csv_files: print(正在处理, csv_file.name) df pd.read_csv(csv_file) # 统一的清洗逻辑 df df.drop_duplicates() df[amount] pd.to_numeric(df[amount], errorscoerce) df[amount] df[amount].fillna(0) df[order_date] pd.to_datetime(df[order_date], errorscoerce) df[user_name] df[user_name].str.strip() # 输出到 clean_data 目录文件名加 clean 前缀 output_path output_dir / fclean_{csv_file.name} df.to_csv(output_path, indexFalse, encodingutf-8-sig) print(已输出, output_path)11.2 增加清洗日志和错误处理批量处理时一个文件出错不能中断整个任务。为每个文件记录处理成功或失败的状态方便后续排查import logging from pathlib import Path import pandas as pd logging.basicConfig( filenameclean_pipeline.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, ) input_dir Path(./raw_data) output_dir Path(./clean_data) output_dir.mkdir(exist_okTrue) csv_files list(input_dir.glob(*.csv)) for csv_file in csv_files: try: df pd.read_csv(csv_file) df df.drop_duplicates() df[amount] pd.to_numeric(df[amount], errorscoerce).fillna(0) df[order_date] pd.to_datetime(df[order_date], errorscoerce) output_path output_dir / fclean_{csv_file.name} df.to_csv(output_path, indexFalse, encodingutf-8-sig) logging.info(f成功处理 {csv_file.name}共 {len(df)} 行) except Exception as e: logging.error(f处理 {csv_file.name} 失败{e})加了日志之后即使某个文件格式异常脚本也能继续处理其他文件。日志文件记录了每个文件的处理状态就算批量跑几万个文件也能快速定位问题文件。11.3 用配置文件管理清洗规则当清洗规则越来越多时建议把规则集中到一个配置里避免在代码中散落大量魔法值。你可以在脚本里定义一个配置字典或者读取一个 YAML 文件。下面是一个简单的配置字典方案clean_config { drop_subset: [order_id], fillna_rules: { amount: 0, status: 未知 }, to_numeric_cols: [amount], date_cols: [order_date], strip_cols: [user_name, status] }然后清洗逻辑统一读配置执行规则变更只改配置文件不动代码主体。这个方法适合团队协作也适合维护一套长期运行的数据清洗任务。12. Pandas 数据处理性能与内存优化技巧大家用 Pandas 最容易遇到的问题就是“数据一大就内存不足”。这里给出几个比较实用的优化方向不涉及分布式架构单机就能做。12.1 按需读取列pd.read_csv()的时候如果只需要其中几列用usecols参数指定列名避免把所有列都读进内存df pd.read_csv(huge_data.csv, usecols[order_id, amount, order_date])12.2 分块读取大文件如果文件过大内存放不下完整数据可以用chunksize分批读取每批处理完就释放内存chunk_iter pd.read_csv(huge_data.csv, chunksize10000) result_parts [] for chunk in chunk_iter: # 对每个 chunk 做相同的清洗处理 chunk[amount] pd.to_numeric(chunk[amount], errorscoerce).fillna(0) result_parts.append(chunk.drop_duplicates()) # 可以立即把清洗结果写入磁盘避免占用内存 chunk.to_csv(clean_chunk.csv, modea, headerFalse, indexFalse)用modea追加写入时第一批数据需要写表头后续批次headerFalse。如果是在循环里追加第一次循环要单独处理。12.3 选择更高效的数据类型把一个object列转成category可以显著降低内存占用尤其当该列只有少数几种类别时。把一个 int64 列转成 int32也能节省一半内存df[order_id] df[order_id].astype(int32) df[status] df[status].astype(category)12.4 使用 process 函数进行向量化操作用 Python 原生循环处理 DataFrame 的每一行是很慢的。能向量化的操作就不要用循环能用df[col].str.replace()就不要用for循环。能用df[col].apply()就不要用iterrows()。能用df.groupby().transform()就不要手动拼接结果。iterrows()处理一万行数据可能还能接受处理百万行数据会非常慢。所有 Pandas 内置方法都是经过 C 语言级别优化的优先使用内置方法处理数据。12.5 处理完成后释放内存在 Jupyter Notebook 里反复运行数据处理时内存里会残留大量中间变量。处理完大表后可以主动释放import gc del df gc.collect()gc.collect()会立刻回收不再使用的对象从而释放内存。如果你的清洗流程比较长建议在每个大步骤的结尾加上这行代码。13. 常见问题与排查方法问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named pandasPandas 未安装或当前 Python 环境不对检查环境pip list查看已安装包pip install pandas或确认激活了正确的虚拟环境读取 CSV 中文乱码文件编码与系统默认编码不一致用文本编辑器查看文件实际编码读取时指定encodingutf-8、encodinggbk或encodingutf-8-sigdf[amount].sum()结果是字符串拼接数值列被读成了字符串打印df.dtypes检查类型使用pd.to_numeric转换errorscoerceValueError: cannot convert float NaN to integer整数列存在缺失值无法直接转 int查看该列缺失值先fillna()填充缺失值再转数值类型pd.to_datetime抛出异常日期字符串格式不统一或存在非法日期先单独提取该列用errorscoerce测试指定format参数或先清洗文本再转换drop_duplicates()没有去除重复重复行的其他列值不同只是看起来像重复先指定subset参数df.drop_duplicates(subset[order_id])读取大文件内存不足数据量太大一次性读入内存估算文件大小和可用内存使用chunksize分批读取或只读取需要的列输出 CSV 后 Excel 打开中文乱码UTF-8 编码被 Excel 识别错误用记事本打开检查编码写入时使用encodingutf-8-sig.str.strip()报AttributeError该列不是字符串类型打印dtypes确认类型先astype(str)再执行字符串方法数据清洗后行数异常减少dropna()删除了过多行或去重规则不合理检查每个步骤的行数变化清洗前记录原始形状逐步对比每个步骤后的形状排查建议每执行一步清洗都打印一次df.shape确认行数和列数是否符合预期。不要等全部步骤跑完再检查那样出了问题很难定位到具体是哪一步。14. 最佳实践与使用建议先讲方法层面的建议。创建一份可重复执行的数据清洗脚本每一次清洗都保存一个中间版本。不要在原文件上直接修改也不要把所有步骤挤在一个 Cell 里。建议按“原始数据 → 中间表1 → 中间表2 → 最终结果”的方式保存后续想追溯某一列的数据来源时会非常方便。再讲规则层面的建议。把清洗规则抽象成函数比如clean_amount()、clean_date()、clean_name()每个函数只处理一种类型的脏数据。这样做的好处是第一代码可复用不同项目可以直接调用第二可测试每次修改规则之后可以重新验证函数输出第三可读性强别人看你的数据清洗脚本时能清楚知道每一步在做什么。下面是一个简单的函数封装示例def clean_price_series(series: pd.Series) - pd.Series: 清洗金额列转数值、非法值置空、空值填0 return pd.to_numeric(series, errorscoerce).fillna(0) def clean_date_series(series: pd.Series) - pd.Series: 清洗日期列统一转成时间类型 return pd.to_datetime(series, errorscoerce) df[amount] clean_price_series(df[amount]) df[order_date] clean_date_series(df[order_date])再讲合规层面的建议。如果你处理的是用户数据、业务数据、金融数据清洗之前先做脱敏设计。比如手机号只保留前三位后四位身份证号中间部分加密处理。数据清洗脚本本身也可能包含敏感信息不要直接提交到公开仓库。涉及人脸、声音、版权素材的数据在清洗、转换、存储前必须确认授权范围。批处理脚本如果你不打算让其他人复用也在项目里加入一行版权和使用说明避免后续团队协作时出现合规争议。最后说一下测试策略。数据清洗脚本正式执行前一定要在一个小的样本集上验证规则是否合理。比如从原始数据中随机抽取 1000 行跑一遍清洗逻辑人工检查清洗后的结果是否符合预期然后再全量运行。批量清洗时先让脚本处理 3 到 5 个文件确认输出无误后再处理全部文件。这样可以减少无效计算也避免批量的错误规则把全量数据改坏。15. 总结与下一步Pandas 数据清洗的核心能力可以归结为四个字查、删、填、转。“查”是发现脏数据“删”是去除重复和无效记录“填”是修复缺失值“转”是统一类型和格式。把这四步走完你的数据基本就能从“原始状态”变成“结构化状态”可以进入分析、可视化或者建模阶段。这篇实战内容里你最应该先跑通的步骤是加载数据后用df.info()和df.isnull().sum()快速判断脏数据类型然后按照缺失值、重复值、类型转换、文本清洗、日期标准化这个顺序逐项修复最后导出为 CSV 或 Parquet 文件。最容易踩的坑是类型转换时没有设置errorscoerce以及去重时没有指定subset参数这两个坑在前 100 行小数据上就能暴露出来不要直接拿全量数据去踩。后续扩展方向包括用matplotlib和seaborn对清洗后的结构化数据做可视化分析用scikit-learn接上分类和回归建模或者把清洗脚本包装成 FastAPI 接口让业务系统实时传入原始表格、返回清洗后的结果。如果你的数据量继续增长单机 Pandas 开始吃力可以考虑换用 PySpark DataFrame两者的 API 设计非常相似过渡成本相对可控。建议你先把这篇文章里的示例代码保存为一个可复用的清洗模板下次拿到新数据时直接替换列名和清洗规则即可。这套方法论和代码逻辑是通用的值得收藏备用。
返回列表