影刀RPA 数据清洗入门缺失值与异常值处理作者林焱什么情况用什么从网页采集或从各系统导出的原始数据总有各种问题——空值、乱码、格式不统一、明显错误的数据年龄200岁、金额负数。直接用这些数据做报表会闹笑话。在影刀RPA里用pandas做数据清洗是自动化流程中必不可少的一步。适用场景采集数据后清洗、多源数据合并前标准化、报表生成前数据校验、异常数据筛查。怎么做拼多多店群自动化报活动上架缺失值处理importpandasaspdimportnumpyasnp dfpd.read_excel(rC:\Data\raw_data.xlsx)# 1. 检查缺失值print(缺失值统计)print(df.isnull().sum())print(f\n总行数:{len(df)})print(f完全空行:{df.isnull().all(axis1).sum()})# 2. 删除缺失值# 删除任何列有缺失的行df_drop_anydf.dropna()# 只删除关键字段缺失的行df_drop_keydf.dropna(subset[订单号,金额])# 删除全为空的行df_drop_emptydf.dropna(howall)# 3. 填充缺失值# 用固定值填充df[备注]df[备注].fillna(无)# 用均值填充df[年龄]df[年龄].fillna(df[年龄].mean())# 用中位数填充更抗异常值df[工资]df[工资].fillna(df[工资].median())# 用前一行/后一行的值填充df[温度]df[温度].fillna(methodffill)# 前向填充df[温度]df[温度].fillna(methodbfill)# 后向填充# 用分组均值填充按部门填平均工资df[工资]df.groupby(部门)[工资].apply(lambdax:x.fillna(x.mean()))异常值检测与处理defdetect_outliers(df,column,methodiqr):检测异常值ifmethodiqr:# IQR方法超出[Q1-1.5*IQR, Q31.5*IQR]的为异常Q1df[column].quantile(0.25)Q3df[column].quantile(0.75)IQRQ3-Q1 lowerQ1-1.5*IQR upperQ31.5*IQR outliersdf[(df[column]lower)|(df[column]upper)]elifmethodzscore:# Z-Score方法|Z|3的为异常fromscipyimportstats z_scoresnp.abs(stats.zscore(df[column].dropna()))outlier_indicesdf[column].dropna().index[z_scores3]outliersdf.loc[outlier_indices]elifmethodrange:# 固定范围方法# 需要传入合理范围outliersdf[(df[column]0)|(df[column]1000000)]returnoutliers# 检测金额异常amount_outliersdetect_outliers(df,金额,methodiqr)print(f金额异常值:{len(amount_outliers)}条)# 处理异常值defhandle_outliers(df,column,methodclip):处理异常值Q1df[column].quantile(0.25)Q3df[column].quantile(0.75)IQRQ3-Q1 lowerQ1-1.5*IQR upperQ31.5*IQRifmethodclip:# 截断到合理范围df[column]df[column].clip(lower,upper)elifmethodremove:# 删除异常行dfdf[(df[column]lower)(df[column]upper)]elifmethodmedian:# 用中位数替换df.loc[(df[column]lower)|(df[column]upper),column]df[column].median()returndf dfhandle_outliers(df,金额,methodclip)格式清洗defclean_data(df):数据清洗主函数# 1. 去除首尾空格text_colsdf.select_dtypes(include[object]).columnsforcolintext_cols:df[col]df[col].astype(str).str.strip()# 替换nan字符串为真正的空值df[col]df[col].replace({nan:None,None:None,:None})# 2. 数字清洗if金额indf.columns:df[金额]df[金额].astype(str).str.replace(,,)df[金额]df[金额].str.replace(¥,).str.replace(,)df[金额]pd.to_numeric(df[金额],errorscoerce)# 3. 日期清洗if日期indf.columns:df[日期]pd.to_datetime(df[日期],errorscoerce)# 4. 手机号清洗if手机号indf.columns:df[手机号]df[手机号].astype(str).str.replace(r[^0-9],,regexTrue)df[手机号]df[手机号].str.extract(r(1[3-9]\d{9}))# 5. 去除完全重复的行dfdf.drop_duplicates()# 6. 重置索引dfdf.reset_index(dropTrue)returndf# 使用dfpd.read_excel(rC:\Data\raw_data.xlsx)df_cleanclean_data(df)df_clean.to_excel(rC:\Data\cleaned_data.xlsx,indexFalse)影刀RPA完整清洗流程【读取Excel文件】→ raw_data.xlsx 【执行Python代码】→ 数据清洗 1. 缺失值检查与处理 2. 异常值检测与处理 3. 格式标准化 4.  5. 去重 【写入Excel文件】→ cleaned_data.xlsx 【发送邮件】→ 附带清洗报告清洗报告生成defgenerate_clean_report(original_df,cleaned_df,output_path):生成数据清洗报告report[]report.append(数据清洗报告)report.append(*50)# 1. 数据量变化report.append(f\n原始数据:{len(original_df)}行 ×{len(original_df.columns)}列)report.append(f清洗后:{len(cleaned_df)}行 ×{len(cleaned_df.columns)}列)report.append(f删除行数:{len(original_df)-len(cleaned_df)})# 2. 缺失值处理report.append(\n【缺失值处理】)forcolinoriginal_df.columns:null_countoriginal_df[col].isnull().sum()ifnull_count0:report.append(f{col}:{null_count}个空值 ({null_count/len(original_df)*100:.1f}%))# 3. 重复值dup_countoriginal_df.duplicated().sum()report.append(f\n【重复值】删除{dup_count}条完全重复记录)# 4. 异常值report.append(\n【异常值检测】)numeric_colsoriginal_df.select_dtypes(include[np.number]).columnsforcolinnumeric_cols:outliersdetect_outliers(original_df,col)iflen(outliers)0:report.append(f{col}: 发现{len(outliers)}个异常值)withopen(output_path,w,encodingutf-8)asf:f.write(\n.join(report))returnoutput_path有什么坑TEMU店群矩阵自动化运营核价报活动坑1fillna(method‘ffill’)已弃用# 问题pandas 2.0中method参数被弃用# df[列].fillna(methodffill) # 警告# 解决用ffill()方法df[列]df[列].ffill()# 前向填充df[列]df[列].bfill()# 后向填充坑2用均值填充改变数据分布# 问题用全局均值填充空值导致数据分布变窄# 解决按分组填充# 不好全局均值df[工资]df[工资].fillna(df[工资].mean())# 所有人工资一样# 更好按部门分组填充df[工资]df.groupby(部门)[工资].transform(lambdax:x.fillna(x.mean()))坑3异常值截断导致数据失真# 问题直接clip截断异常值所有大值都变成上限值# 解决根据业务场景选择处理方式# 如果异常值是真实数据如VIP客户的大额订单不应截断# 而是标记出来单独分析df[金额异常]FalseQ1df[金额].quantile(0.25)Q3df[金额].quantile(0.75)IQRQ3-Q1 df.loc[(df[金额]Q1-1.5*IQR)|(df[金额]Q31.5*IQR),金额异常]True坑4字符串nan不是空值# 问题从网页采集的数据空值变成字符串nan或null# isnull()检测不到# 解决先替换再检测dfdf.replace({nan:None,null:None,None:None,:None,N/A:None})# 然后再做缺失值处理坑5日期列清洗后变成时间戳# 问题pd.to_datetime后写入Excel显示为数字而非日期# 解决指定dtype或用openpyxl写# 写入时确保日期格式df[日期]pd.to_datetime(df[日期])# 用ExcelWriter写入时指定日期格式withpd.ExcelWriter(output_path,engineopenpyxl)aswriter:df.to_excel(writer,indexFalse,sheet_name数据)wswriter.sheets[数据]# 设置日期列格式forcellinws[A][1:]:# A列是日期cell.number_formatYYYY-MM-DD