Pandas 在数据清洗中的实际应用 1. 引言为什么数据清洗如此重要在数据分析和机器学习项目中数据清洗通常占据70%-80%的时间。原始数据往往是不完整的缺失值不一致的格式不统一、单位混淆不准确的异常值、错误录入重复的包含噪声Pandas 作为 Python 数据分析的核心库提供了强大而灵活的工具来处理上述问题。本指南将通过大量实际代码展示如何利用 Pandas 完成高效的数据清洗工作。2. Pandas 基础回顾与安装2.1 安装与导入bashpip install pandas # 通常还会安装 numpy, openpyxl, xlrd 等辅助库 pip install numpy openpyxl xlrd导入pythonimport pandas as pd import numpy as np # 设置显示选项便于查看 pd.set_option(display.max_rows, 100) pd.set_option(display.max_columns, 20) pd.set_option(display.width, 1000)2.2 核心数据结构Series一维带标签数组DataFrame二维表格结构类似于 Excel 表格3. 数据加载与初步探索3.1 读取常见文件格式python# CSV df pd.read_csv(data.csv, encodingutf-8) # Excel (需要 openpyxl 或 xlrd) df pd.read_excel(data.xlsx, sheet_nameSheet1) # JSON df pd.read_json(data.json) # SQL 数据库 import sqlite3 conn sqlite3.connect(database.db) df pd.read_sql_query(SELECT * FROM table, conn) # 从剪贴板读取适合快速测试 df pd.read_clipboard()3.2 参数调优在读取大数据时常用参数nrows1000只读取前1000行用于测试usecols[col1,col2]只读取指定列dtype{col1: str}指定列的数据类型避免后续转换parse_dates[date_col]自动解析日期列3.3 初步探索python# 查看前5行 df.head() # 查看后5行 df.tail() # 查看数据形状 df.shape # 查看列名 df.columns.tolist() # 查看数据类型 df.dtypes # 查看基本信息索引类型、列类型、内存占用 df.info() # 查看统计描述数值列 df.describe() # 查看分类列的统计 df[category_col].value_counts() # 查看缺失值情况 df.isnull().sum() # 查看缺失值比例 df.isnull().sum() / len(df) * 1004. 处理缺失值缺失值NaN/None是数据清洗中最常见的问题。4.1 识别缺失值python# 检测缺失值 df.isnull() # 返回布尔型 DataFrame df.isnull().sum() # 每列缺失数量 # 检测非缺失值 df.notnull() # 找出有缺失值的行 df[df.isnull().any(axis1)] # 特定列有缺失值的行 df[df[col_name].isnull()]4.2 删除缺失值python# 删除任何包含缺失值的行 df.dropna() # 删除任何包含缺失值的列 df.dropna(axis1) # 要求至少保留指定数量的非缺失值 df.dropna(threshlen(df)*0.8, axis1) # 保留非缺失比例80%的列 # 仅当某列缺失时才删除行 df.dropna(subset[col1, col2])4.3 填充缺失值4.3.1 常数填充python# 填充固定值 df.fillna(0) # 数值列填充0 df.fillna(Unknown) # 字符串列填充未知 # 不同列填充不同值 df.fillna({col1: 0, col2: missing, col3: df[col3].mean()})4.3.2 统计量填充python# 均值/中位数/众数填充 df[col].fillna(df[col].mean(), inplaceTrue) df[col].fillna(df[col].median(), inplaceTrue) df[col].fillna(df[col].mode()[0], inplaceTrue) # 前向填充用上一个非缺失值填充 df.fillna(methodffill) df.fillna(methodpad) # 后向填充 df.fillna(methodbfill) df.fillna(methodbackfill)4.3.3 插值法python# 线性插值 df[col].interpolate(methodlinear, inplaceTrue) # 多项式插值 df[col].interpolate(methodpolynomial, order2, inplaceTrue) # 时间序列插值 df[col].interpolate(methodtime, inplaceTrue)4.3.4 使用模型预测填充高级对于重要特征可以使用 KNN、回归等算法预测缺失值。4.4 缺失值处理原则缺失率 5%可直接删除或简单填充5% 缺失率 30%根据业务选择填充方式缺失率 30%考虑删除该特征或作为单独类别处理5. 处理重复值5.1 识别重复值python# 检查整行重复 df.duplicated() # 返回布尔 Series df.duplicated().sum() # 重复行数 # 基于特定列检查重复 df.duplicated(subset[col1, col2]) # 查看重复的行 df[df.duplicated(keepFalse)] # keepFalse 显示所有重复行5.2 删除重复值python# 删除完全重复的行保留第一次出现 df.drop_duplicates(inplaceTrue) # 基于特定列删除重复 df.drop_duplicates(subset[col1, col2], keepfirst) # 保留最后一次出现 df.drop_duplicates(keeplast) # 删除所有重复行只保留唯一行 df.drop_duplicates(keepFalse)5.3 标记重复值python# 标记是否重复 df[is_duplicated] df.duplicated()6. 数据类型转换与优化6.1 查看数据类型pythondf.dtypes df.info(memory_usagedeep) # 查看详细内存占用6.2 转换数据类型python# 转换为字符串 df[col] df[col].astype(str) # 转换为数值处理错误 df[col] pd.to_numeric(df[col], errorscoerce) # 无法转换的变为 NaN # 转换为日期 df[date] pd.to_datetime(df[date], format%Y-%m-%d, errorscoerce) # 转换为分类类型节省内存提高性能 df[category] df[category].astype(category)6.3 类型优化技巧python# 将整数列转为更小的类型int8, int16, int32 from pandas.api.types import CategoricalDtype # 对于取值较少的字符串列转为 category 类型 df[gender] df[gender].astype(category) # 查看内存优化效果 df.memory_usage(deepTrue)6.4 处理混合类型列有时一列中同时包含数字和字符串需要先清洗再转换。python# 提取数字部分 df[price] df[price].str.extract((\d\.?\d*)).astype(float) # 替换特殊字符后转换 df[amount] df[amount].str.replace($, ).str.replace(,, ).astype(float)7. 异常值检测与处理7.1 数值型异常值检测7.1.1 描述统计法python# 查看基本统计量 df.describe() # 找出超出 3 倍标准差的值 mean df[col].mean() std df[col].std() outliers df[(df[col] mean - 3*std) | (df[col] mean 3*std)]7.1.2 箱线图法IQRpythonQ1 df[col].quantile(0.25) Q3 df[col].quantile(0.75) IQR Q3 - Q1 lower_bound Q1 - 1.5 * IQR upper_bound Q3 1.5 * IQR outliers df[(df[col] lower_bound) | (df[col] upper_bound)]7.1.3 Z-score 法pythonfrom scipy import stats z_scores np.abs(stats.zscore(df[col])) outliers df[z_scores 3]7.2 分类型异常值检测python# 查看类别分布 df[category].value_counts() # 找出出现次数极少的类别如少于5次 rare_categories df[category].value_counts()[df[category].value_counts() 5].index df[category] df[category].replace(rare_categories, Other)7.3 异常值处理方式7.3.1 删除异常值python# 删除超出 IQR 范围的行 df_clean df[(df[col] lower_bound) (df[col] upper_bound)]7.3.2 截断Winsorizepython# 将超出边界的值替换为边界值 df[col] df[col].clip(lowerlower_bound, upperupper_bound)7.3.3 替换为缺失值pythondf.loc[(df[col] lower_bound) | (df[col] upper_bound), col] np.nan7.3.4 分箱处理python# 将连续变量分箱减少异常值影响 df[col_binned] pd.cut(df[col], bins10)8. 字符串文本清洗8.1 基本字符串操作python# 去除首尾空格 df[col] df[col].str.strip() df[col] df[col].str.lstrip() df[col] df[col].str.rstrip() # 大小写转换 df[col] df[col].str.lower() df[col] df[col].str.upper() df[col] df[col].str.title() # 替换 df[col] df[col].str.replace(old, new, regexFalse) df[col] df[col].str.replace(r\d, , regexTrue) # 删除所有数字8.2 分割与提取python# 分割字符串为多列 df[[first_name, last_name]] df[full_name].str.split( , expandTrue) # 提取正则表达式匹配的部分 df[phone] df[text].str.extract(r(\d{3}-\d{4}-\d{4})) # 提取所有匹配 df[emails] df[text].str.findall(r[\w\.-][\w\.-]\.\w) # 获取字符串长度 df[len] df[col].str.len()8.3 条件判断与过滤python# 是否包含子串 df[df[col].str.contains(keyword, naFalse)] # 是否以指定字符串开头/结尾 df[df[col].str.startswith(A)] df[df[col].str.endswith(.pdf)] # 是否全为数字 df[col].str.isdigit() # 是否全为字母 df[col].str.isalpha()8.4 处理特殊字符python# 删除所有标点符号 import string df[col] df[col].str.translate(str.maketrans(, , string.punctuation)) # 删除空格和换行符 df[col] df[col].str.replace(\s, , regexTrue).str.strip() # 统一编码问题 df[col] df[col].str.encode(utf-8).str.decode(utf-8)9. 日期时间数据处理9.1 解析日期python# 自动解析 df[date] pd.to_datetime(df[date], errorscoerce) # 指定格式 df[date] pd.to_datetime(df[date], format%d/%m/%Y) # 处理多种格式 df[date] pd.to_datetime(df[date], infer_datetime_formatTrue)9.2 提取日期成分python# 提取年、月、日、星期等 df[year] df[date].dt.year df[month] df[date].dt.month df[day] df[date].dt.day df[weekday] df[date].dt.weekday # 0周一, 6周日 df[weekday_name] df[date].dt.day_name() df[quarter] df[date].dt.quarter df[hour] df[date].dt.hour df[minute] df[date].dt.minute # 判断是否周末 df[is_weekend] df[date].dt.weekday 59.3 日期范围与偏移python# 生成日期范围 date_range pd.date_range(start2023-01-01, end2023-12-31, freqD) # 日期加减 df[date] pd.Timedelta(days7) df[date] - pd.DateOffset(months1) # 计算时间差 df[days_diff] (df[end_date] - df[start_date]).dt.days9.4 处理时区python# 本地化 df[date] df[date].dt.tz_localize(UTC) # 转换时区 df[date] df[date].dt.tz_convert(Asia/Shanghai)10. 数据重塑与透视10.1 行列转置python# 转置整个 DataFrame df.T # melt: 宽表变长表列变行 df_melted pd.melt(df, id_vars[id], value_vars[col1, col2], var_namevariable, value_namevalue) # pivot: 长表变宽表行变列 df_pivoted df.pivot(indexdate, columnscity, valuestemperature) # pivot_table: 带聚合的透视 df_pivot pd.pivot_table(df, valuessales, indexdate, columnsproduct, aggfuncsum, fill_value0)10.2 堆叠与拆堆叠python# stack: 将列索引转为行索引 df_stacked df.stack() # unstack: 将行索引转为列索引 df_unstacked df.unstack()10.3 分层索引处理python# 设置多级索引 df.set_index([year, month], inplaceTrue) # 按层级选择 df.loc[2023] df.loc[(2023, 6)] # 重置索引 df.reset_index(inplaceTrue)11. 数据合并与连接11.1 concat: 简单拼接python# 纵向拼接行增加 df_concat pd.concat([df1, df2], axis0, ignore_indexTrue) # 横向拼接列增加 df_concat pd.concat([df1, df2], axis1) # 处理索引重复 df_concat pd.concat([df1, df2], verify_integrityTrue) # 检查重复索引11.2 merge: 数据库风格连接python# 内连接只保留键匹配的行 merged pd.merge(df1, df2, onkey, howinner) # 左连接保留左表所有行 merged pd.merge(df1, df2, onkey, howleft) # 右连接 merged pd.merge(df1, df2, onkey, howright) # 外连接保留所有键 merged pd.merge(df1, df2, onkey, howouter) # 多键连接 merged pd.merge(df1, df2, on[key1, key2]) # 不同列名连接 merged pd.merge(df1, df2, left_onkey_left, right_onkey_right)11.3 join: 基于索引连接python# 基于索引连接 df1.join(df2, howleft) # 指定左表列和右表索引 df1.set_index(key).join(df2.set_index(key))11.4 处理重复列名python# 自动添加后缀 merged pd.merge(df1, df2, onkey, suffixes(_left, _right))12. 分组聚合与变换12.1 基础分组聚合python# 单列分组单列聚合 df.groupby(category)[value].mean() # 多列分组多列聚合 df.groupby([category, region])[[value, amount]].agg([mean, sum, count]) # 使用字典指定不同列的聚合函数 df.groupby(category).agg({ value: mean, amount: [sum, max], date: min })12.2 自定义聚合函数python# 使用 lambda df.groupby(category)[value].agg(lambda x: x.max() - x.min()) # 使用自定义函数 def range_func(x): return x.max() - x.min() df.groupby(category)[value].agg(range_func) # 多个自定义函数 df.groupby(category)[value].agg([mean, range_func])12.3 transform: 分组内变换python# 填充组内均值 df[value_filled] df.groupby(category)[value].transform(lambda x: x.fillna(x.mean())) # 组内排名 df[rank_in_group] df.groupby(category)[value].rank() # 组内标准化 df[normalized] df.groupby(category)[value].transform(lambda x: (x - x.mean()) / x.std())12.4 filter: 分组过滤python# 保留组内样本数大于5的组 df_filtered df.groupby(category).filter(lambda x: len(x) 5) # 保留组内均值大于阈值的组 df_filtered df.groupby(category).filter(lambda x: x[value].mean() 100)13. 高级技巧13.1 管道函数 (pipe)python# 定义清洗函数 def clean_missing(df): return df.dropna(subset[important_col]) def clean_outliers(df): # 异常值处理逻辑 return df def convert_types(df): # 类型转换逻辑 return df # 使用管道串联 df_clean (df .pipe(clean_missing) .pipe(clean_outliers) .pipe(convert_types) )13.2 自定义函数应用python# apply: 按行或按列应用函数 df[new_col] df.apply(lambda row: row[col1] row[col2], axis1) # applymap: 元素级应用 df df.applymap(lambda x: x.strip() if isinstance(x, str) else x) # map: Series 级映射 df[gender_code] df[gender].map({Male: 1, Female: 0}) # replace: 多值替换 df[category] df[category].replace({A: Category A, B: Category B})13.3 向量化操作性能优化python# 避免使用 apply优先使用向量化操作 # 不推荐 df[new] df.apply(lambda x: x[a] x[b], axis1) # 推荐 df[new] df[a] df[b] # 条件赋值向量化 df[category] np.where(df[value] 100, High, Low)13.4 链式操作与视图 vs 副本python# 使用 loc 确保修改原数据 df.loc[df[col] 0, new_col] 1 # 避免 SettingWithCopyWarning # 错误df[df[col]0][new_col] 1 # 正确df.loc[df[col]0, new_col] 1 # 显式复制 df_copy df.copy()14. 实战案例一用户行为日志清洗场景某 App 的用户行为日志包含用户 ID、时间戳、行为类型、页面、设备信息等需要清洗成可用于分析的格式。数据样例textuser_id, timestamp, event, page, device, ip 1001,2023-10-01 10:23:45,click,home, iPhone 12,192.168.1.1 1002,2023-10-01 10:24:01,view,product, Android,192.168.1.2 1001,2023-10-01 10:25:00,click,product, iPhone 12,192.168.1.1 1003,2023-10-01 10:26:30,purchase,checkout, iPad,192.168.1.3 ,,,,清洗步骤pythonimport pandas as pd import numpy as np # 1. 读取数据指定数据类型 df pd.read_csv(user_logs.csv, parse_dates[timestamp], dtype{user_id: Int64, event: category}) # 2. 删除完全空的行 df.dropna(howall, inplaceTrue) # 3. 处理缺失值 # 检查缺失情况 print(df.isnull().sum()) # 删除 user_id 为空的记录核心字段 df.dropna(subset[user_id], inplaceTrue) # 填充设备缺失为 Unknown df[device] df[device].fillna(Unknown) # 4. 清洗 device 列统一格式 df[device] df[device].str.strip().str.lower() df[device] df[device].replace({ iphone 12: iPhone12, android: Android, ipad: iPad }) # 5. 提取日期成分 df[date] df[timestamp].dt.date df[hour] df[timestamp].dt.hour df[weekday] df[timestamp].dt.day_name() # 6. 添加会话标识按用户ID和30分钟间隔 df df.sort_values([user_id, timestamp]) df[time_diff] df.groupby(user_id)[timestamp].diff().dt.total_seconds() / 60 df[new_session] (df[time_diff] 30) | (df[time_diff].isnull()) df[session_id] df.groupby(user_id)[new_session].cumsum() # 7. 处理重复点击同一用户同一页面连续点击视为一次 df[prev_page] df.groupby(user_id)[page].shift() df[is_consecutive] (df[page] df[prev_page]) (df[event] click) df df[~df[is_consecutive]] # 8. 删除辅助列 df.drop([time_diff, new_session, prev_page, is_consecutive], axis1, inplaceTrue) # 9. 最终检查 print(df.info()) print(df.head())15. 实战案例二销售数据清洗与聚合场景某零售企业月度销售数据包含订单 ID、日期、产品、单价、数量、客户信息等存在重复订单、价格异常、负数数量等问题。数据样例textorder_id,order_date,product,price,quantity,customer_name,customer_region A001,2023-01-15,Product X,$19.99,2,John Smith,North A002,2023-01-15,Product Y,24.99,-1,Jane Doe,South A001,2023-01-15,Product X,$19.99,2,John Smith,North A003,2023-01-16,Product Z,NaN,3,Bob Johnson,East A004,2023-01-16,Product X,$19.99,100,Alice Lee,North清洗步骤python# 1. 加载数据 df pd.read_csv(sales_data.csv, parse_dates[order_date]) # 2. 处理重复订单完全重复 print(f重复行数: {df.duplicated().sum()}) df.drop_duplicates(inplaceTrue) # 3. 处理价格列 # 去除美元符号并转为数值 df[price] df[price].astype(str).str.replace($, ).str.replace(,, ) df[price] pd.to_numeric(df[price], errorscoerce) # 4. 处理数量异常负数、过大 # 负数数量转为缺失或修正 df.loc[df[quantity] 0, quantity] np.nan # 数量超过 100 视为异常标记并填充均值 df.loc[df[quantity] 100, quantity] np.nan # 5. 填充缺失的价格和数量 # 使用同类产品的平均价格填充 df[price] df.groupby(product)[price].transform(lambda x: x.fillna(x.median())) # 使用产品的中位数数量填充 df[quantity] df.groupby(product)[quantity].transform(lambda x: x.fillna(x.median())) # 6. 计算总金额 df[total] df[price] * df[quantity] # 7. 客户名称清洗 df[customer_name] df[customer_name].str.strip().str.title() # 合并相同客户的变体示例John Smith 和 John A. Smith # 这里简化实际需要更复杂的模糊匹配 # 8. 处理异常日期如果存在未来日期 today pd.Timestamp.now() df df[df[order_date] today] # 9. 添加年月列用于后续分析 df[year_month] df[order_date].dt.to_period(M) # 10. 按产品和月份聚合 monthly_sales df.groupby([year_month, product]).agg({ quantity: sum, total: sum, order_id: nunique }).rename(columns{order_id: order_count}) print(monthly_sales.head()) # 11. 保存清洗后的数据 df.to_csv(sales_cleaned.csv, indexFalse)16. 实战案例三多源数据整合清洗场景从三个不同系统导出用户信息需要整合成统一的用户主数据。系统 A 提供基本信息系统 B 提供消费记录系统 C 提供会员等级。数据存在不一致、缺失和格式差异。数据准备python# 系统 A用户基本信息 df_a pd.DataFrame({ user_id: [1, 2, 3, 4], name: [张三, 李四, 王五, 赵六], phone: [13811112222, 13933334444, 13755556666, 13677778888], register_date: [2023-01-01, 2023-02-01, 2023-03-01, 2023-04-01] }) # 系统 B消费记录可能有重复用户 df_b pd.DataFrame({ uid: [1, 2, 2, 3, 5], amount: [100, 200, 150, 300, 50], order_date: [2023-05-01, 2023-05-02, 2023-05-03, 2023-05-04, 2023-05-05] }) # 系统 C会员等级 df_c pd.DataFrame({ UserID: [1, 2, 3, 6], membership: [Gold, Silver, Platinum, Gold], points: [1200, 800, 2500, 300] })清洗整合步骤python# 1. 统一各表的列名和数据类型 df_a.columns df_a.columns.str.lower() df_b.rename(columns{uid: user_id}, inplaceTrue) df_c.rename(columns{UserID: user_id}, inplaceTrue) # 2. 处理日期字段 df_a[register_date] pd.to_datetime(df_a[register_date]) df_b[order_date] pd.to_datetime(df_b[order_date]) # 3. 清洗姓名去除空格 df_a[name] df_a[name].str.strip() # 4. 清洗手机号统一格式 df_a[phone] df_a[phone].astype(str).str.replace(r\D, , regexTrue) # 5. 消费数据聚合按用户汇总 df_b_agg df_b.groupby(user_id).agg({ amount: [sum, mean, count], order_date: [min, max] }).reset_index() df_b_agg.columns [user_id, total_amount, avg_amount, order_count, first_order, last_order] # 6. 合并所有表外连接保留所有用户 df_merged df_a.merge(df_b_agg, onuser_id, howouter) df_merged df_merged.merge(df_c, onuser_id, howouter) # 7. 处理合并后的缺失值 # 缺失的消费字段填充0 df_merged[[total_amount, avg_amount, order_count]] df_merged[[total_amount, avg_amount, order_count]].fillna(0) # 缺失的会员等级填充 None df_merged[membership] df_merged[membership].fillna(None) df_merged[points] df_merged[points].fillna(0) # 8. 创建用户生命周期特征 df_merged[lifetime_days] (pd.Timestamp.now() - df_merged[register_date]).dt.days df_merged[avg_monthly_spend] df_merged[total_amount] / (df_merged[lifetime_days] / 30) # 9. 检查重复用户 print(f重复用户数: {df_merged[user_id].duplicated().sum()}) # 10. 最终输出 print(df_merged.info()) print(df_merged.head())17. 性能优化与大数据量处理当数据量超过内存容量时需要采用特殊策略。17.1 分块读取python# 分块处理大 CSV chunk_size 100000 chunks [] for chunk in pd.read_csv(large_file.csv, chunksizechunk_size): # 对每个 chunk 进行清洗 chunk_clean clean_function(chunk) chunks.append(chunk_clean) df_clean pd.concat(chunks, ignore_indexTrue)17.2 使用更高效的数据类型python# 优化内存 def optimize_dtypes(df): for col in df.columns: if df[col].dtype object: # 字符串列转为 category 如果唯一值较少 if df[col].nunique() / len(df) 0.5: df[col] df[col].astype(category) elif df[col].dtype int64: # 整数列向下转型 col_min df[col].min() col_max df[col].max() if col_min np.iinfo(np.int8).min and col_max np.iinfo(np.int8).max: df[col] df[col].astype(int8) elif col_min np.iinfo(np.int16).min and col_max np.iinfo(np.int16).max: df[col] df[col].astype(int16) elif col_min np.iinfo(np.int32).min and col_max np.iinfo(np.int32).max: df[col] df[col].astype(int32) return df17.3 使用 Dask 进行并行处理pythonimport dask.dataframe as dd # 读取大文件为 Dask DataFrame ddf dd.read_csv(large_file.csv) # 执行清洗操作惰性计算 ddf_clean ddf.dropna(subset[important_col]) ddf_clean ddf_clean.map_partitions(clean_function) # 触发计算并保存 ddf_clean.to_csv(cleaned_*.csv, indexFalse)17.4 使用 PySpark 处理超大数据对于 TB 级数据推荐使用 PySpark。18. 数据清洗的最佳实践18.1 建立清洗流程文档记录每一步的操作目的保存清洗前后的数据样本使用 Jupyter Notebook 保留执行过程18.2 版本控制对清洗后的数据打标签保存清洗代码到 Git18.3 自动化清洗编写可复用的清洗函数使用 Airflow 或 Prefect 构建数据管道18.4 数据质量检查清单pythondef data_quality_report(df): 生成数据质量报告 report { shape: df.shape, missing_rate: (df.isnull().sum() / len(df)).to_dict(), duplicate_rows: df.duplicated().sum(), unique_counts: df.nunique().to_dict(), data_types: df.dtypes.to_dict(), numeric_stats: df.describe(includenumber).to_dict(), categorical_stats: df.describe(includeobject).to_dict() } return report18.5 常见陷阱与注意事项避免 inplaceTrue 的链式操作可能导致视图与副本混淆警惕 SettingWithCopyWarning使用.loc或显式.copy()检查索引的唯一性合并前确保索引不冲突注意时区问题处理时间数据时明确时区保留原始数据备份清洗前始终备份原始数据19. 总结Pandas 为数据清洗提供了全面的解决方案。本文从基础到高级涵盖了清洗环节核心方法关键技巧缺失值处理dropna,fillna,interpolate根据缺失率选择策略重复值处理duplicated,drop_duplicates基于子集去重类型转换astype,to_numeric,to_datetime处理混合类型异常值处理IQR, Z-score, 分箱结合业务知识文本清洗str方法, 正则表达式批量替换、提取日期处理dt访问器提取特征、计算间隔数据重塑melt,pivot,stack宽表长表互转数据合并merge,concat,join多表关联分组聚合groupby,agg,transform自定义聚合性能优化分块、类型优化、向量化处理大数据数据清洗不仅仅是技术工作更是对业务理解的体现。优秀的清洗流程应当可复现代码化所有操作可追溯记录每一步的决策依据可扩展能够适应新的数据源和业务需求通过掌握上述 Pandas 清洗技巧你将能够高效地将原始数据转化为高质量的分析就绪数据为后续的数据分析和机器学习奠定坚实基础。附录常用正则表达式速查用途表达式匹配邮箱[\w\.-][\w\.-]\.\w匹配手机号中国1[3-9]\d{9}匹配数字\d匹配浮点数\d\.?\d*匹配日期 YYYY-MM-DD\d{4}-\d{2}-\d{2}删除所有标点[^\w\s]