ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

07-Pandas数据清洗:

07-Pandas数据清洗: 为什么要做数据清洗因为真实数据都是脏的。有空值、有重复、有格式不对的、有错别字。直接拿脏数据分析结果肯定不靠谱。这是数据分析里最花时间的一步但也是最基础的一步。 这么说吧——数据清洗就像洗菜。菜上有泥、有烂叶子、有虫子你不能直接下锅。得先洗干净了炒出来的菜才能吃。数据分析也是一个道理。今天这篇咱们用一份个人账单数据当例子把最常见的四类脏数据问题一次性讲透缺失值空值重复值数据类型不对字符串格式乱每一种都告诉你怎么发现、怎么处理、什么时候用哪种方法。一、先造一份脏数据跟着练光说不练假把式。咱们先自己造一份有各种问题的账单数据你可以把下面这段代码复制到 Jupyter 或者 Python 文件里跑一下。importpandasaspdimportnumpyasnp# 造一份脏数据——模拟真实场景下的个人账单data{日期:[2024-01-05,2024/01/06,2024-01-07,2024-01-08,2024/01/09,2024-01-10,2024-01-05,2024-01-11,2024-01-12,2024-01-13],类别:[餐饮 ,餐饮, 交通,购物,餐饮,娱乐,餐饮 , 交通 ,购物,np.nan],金额:[¥35.5,¥128,¥15.00,¥299,88元,¥56.8,¥35.5,¥20,¥199.9,¥66],支付方式:[微信,支付宝,微信,np.nan,微信,支付宝,微信,微信,银行卡,微信],备注:[午餐,火锅,地铁,np.nan,奶茶,电影票,午餐,打车,衣服,超市]}dfpd.DataFrame(data)print(原始脏数据)print(df)跑出来你会看到这份数据里藏了好几个坑日期格式不统一有的是2024-01-05有的是2024/01/06类别列有空格餐饮 和餐饮看起来一样但实际不一样金额是字符串还带了¥符号甚至有一个写的是88元有缺失值支付方式、类别、备注里都有空值有重复行第7行和第1行索引0和6几乎一模一样就是重复录入了真实工作中你拿到的 Excel、CSV大概率比这个还脏。咱们一个一个来收拾。二、第一类问题缺失值空值缺失值就是数据里缺了一块Pandas 里一般显示为NaN或者None。1. 怎么发现缺失值先看看每列缺了多少个# 查看每列缺失值数量print(df.isnull().sum())输出大概长这样日期 0 类别 1 金额 0 支付方式 1 备注 1 dtype: int64df.isnull()会把整个表格变成 True/False空的地方就是 True.sum()把每列的 True 加起来就是缺失的数量还可以用df.info()一次性看整体情况df.info()2. 处理方式一直接删除如果缺失的很少而且那一列不是特别关键可以直接删掉。# 删除所有包含空值的行df_dropdf.dropna()⚠️注意dropna()不会改变原来的 df它返回一个新的 DataFrame。你得赋值回去或者加inplaceTrue。# 方式1赋值回去dfdf.dropna()# 方式2inplaceTrue 直接修改原数据df.dropna(inplaceTrue)还可以按列删或者只删全是空的行# 删除整行都是空的df.dropna(howall)# 删除指定列有空值的行df.dropna(subset[支付方式])什么时候用删除缺得很少比如1000条里缺了3条、删掉不影响整体分析的时候。3. 处理方式二填充值有时候不能删得填上。比如金额列缺了你可以填0类别缺了可以填其他。# 全部空值填成0df.fillna(0)# 全部空值填成未知df.fillna(未知)4. 处理方式三按列分别处理实战中一般不会所有列都用同一种方式填而是一列一列来# 字典形式指定每列填什么df_filleddf.fillna({类别:其他,支付方式:未知,备注:无备注})这样更合理——类别缺了就归到其他支付方式缺了就标未知备注缺了就写无备注。5. 进阶玩法用前一个值填充向前填充# 前面的值是什么空的就填什么df.ffill()# 或者 df.fillna(methodffill)这个适合时间序列数据比如前一天的温度是空的就用后一天的补上。用平均值/中位数填充# 注意金额现在还是字符串转成数字之后才能算均值# 先转成数字后面会讲然后df[金额].fillna(df[金额].mean())数值型数据缺了用均值或者中位数填也是很常见的做法。三、第二类问题重复值重复值就是同一行数据出现了好几次。常见于手动录入、多次导入合并的时候。1. 怎么发现重复值# 看有多少行重复print(df.duplicated().sum())# 把重复的行显示出来df[df.duplicated(keepFalse)]duplicated()返回每一行是不是重复的True/FalsekeepFalse表示把所有重复的都标出来默认只标第一次出现之后的2. 怎么删除重复值# 删除完全重复的行df_uniquedf.drop_duplicates()和dropna()一样默认不会改原数据要赋值回去或者加inplaceTrue。3. 按指定列去重有时候不是整行都重复而是某几列重复就算重复。比如同一天同一金额的账单可能就是录重了。# 按日期和金额两列来去重df.drop_duplicates(subset[日期,金额],keepfirst)subset指定按哪些列判断重复keepfirst保留第一次出现的删掉后面的keeplast保留最后一次的keepFalse重复的全删掉四、第三类问题数据类型不对这个是新手最容易踩坑的地方。看着像数字但其实是字符串一算就报错。咱们这份数据里金额列带了¥符号肯定是字符串类型。先确认一下print(df.dtypes)你会看到金额列是object类型Pandas 里字符串就是 object日期列也是 object。1. 金额列字符串转数字首先得把¥符号和元字去掉然后再转成数字。# 去掉¥符号df[金额]df[金额].str.replace(¥,,regexFalse)# 去掉元字df[金额]df[金额].str.replace(元,,regexFalse)# 转成浮点数df[金额]df[金额].astype(float)⚠️新手常见坑如果数据里有奇怪的字符比如待定、--这种直接astype(float)会报错。这时候用pd.to_numeric()更安全# 转不了的就变成空值NaNdf[金额]pd.to_numeric(df[金额],errorscoerce)errorscoerce的意思是——转不了就拉倒给我变成空值。后面再统一处理空值就行。2. 日期列字符串转日期类型df[日期]pd.to_datetime(df[日期],formatmixed)Pandas 的to_datetime()能识别2024-01-05和2024/01/06这种混合格式新版 Pandas3.x需要加formatmixed告诉它不要纠结格式。转换完再检查一下print(df.dtypes)print(---)print(df[日期].dt.year.head())# 现在可以直接取年份了看到日期列变成datetime64[ns]类型金额列变成float64就对了。五、第四类问题字符串规整字符串的问题五花八门——前后有空格、大小写不一致、格式乱七八糟。Pandas 的str系列方法就是专门干这个的。1. 去空格# 去掉前后空格df[类别]df[类别].str.strip()# 只去左边空格 str.lstrip()# 只去右边空格 str.rstrip()咱们的账单数据里餐饮 和 交通 这种strip 之后就变成正常的餐饮、交通了。2. 统一大小写英文列很常用比如类别如果是Food、food、FOOD混着来先统一了再说# 全部转小写df[类别]df[类别].str.lower()# 全部转大写df[类别]df[类别].str.upper()3. 替换内容前面转金额的时候已经用过了就是str.replace()# 把¥换成空df[金额]df[金额].str.replace(¥,,regexFalse)⚠️ 注意Pandas 新版本里replace默认是正则表达式模式如果你就是想替换普通字符串加上regexFalse更安全。4. 字符串分列比如你想把2024-01-05拆成年、月、日三列或者从2024-01里提取年和月。# 先确保是字符串然后用 split 拆分df[年]df[日期].dt.year# 日期类型直接取年更方便df[月]df[日期].dt.month# 如果是纯字符串列比如2024-01这种格式# df[[年, 月]] df[年月].str.split(-, expandTrue)expandTrue的意思是把拆分结果展开成多列而不是变成一个列表。六、完整清洗流程演示上面是拆开来一个一个讲现在咱们从头到尾完整走一遍。从最脏的原始数据到最后干干净净的成品。importpandasaspdimportnumpyasnp# 第一步读取数据 data{日期:[2024-01-05,2024/01/06,2024-01-07,2024-01-08,2024/01/09,2024-01-10,2024-01-05,2024-01-11,2024-01-12,2024-01-13],类别:[餐饮 ,餐饮, 交通,购物,餐饮,娱乐,餐饮 , 交通 ,购物,np.nan],金额:[¥35.5,¥128,¥15.00,¥299,88元,¥56.8,¥35.5,¥20,¥199.9,¥66],支付方式:[微信,支付宝,微信,np.nan,微信,支付宝,微信,微信,银行卡,微信],备注:[午餐,火锅,地铁,np.nan,奶茶,电影票,午餐,打车,衣服,超市]}dfpd.DataFrame(data)print(【清洗前】共,len(df),条数据)print(df)print()# 第二步去重 # 先去重因为重复行后面处理也是白忙活dfdf.drop_duplicates()print(【去重后】还剩,len(df),条数据)print()# 第三步字符串规整 # 类别列去空格df[类别]df[类别].str.strip()# 金额列清理符号df[金额]df[金额].str.replace(¥,,regexFalse)df[金额]df[金额].str.replace(元,,regexFalse)print(【字符串规整后】)print(df[[类别,金额]].head())print()# 第四步类型转换 # 金额转数字df[金额]pd.to_numeric(df[金额],errorscoerce)# 日期转日期类型df[日期]pd.to_datetime(df[日期],formatmixed)print(【类型转换后】各列类型)print(df.dtypes)print()# 第五步处理缺失值 # 金额列有空值填0df[金额]df[金额].fillna(0)# 类别列空值填其他df[类别]df[类别].fillna(其他)# 支付方式填未知df[支付方式]df[支付方式].fillna(未知)# 备注填无df[备注]df[备注].fillna(无)print(【缺失值处理后】空值数量)print(df.isnull().sum())print()# 第六步看看最终成果 print(*50)print(【清洗完成最终数据】)print(df)你可以完整跑一遍这段代码看着数据一步一步变干净还是挺有成就感的 真实运行效果把上面的完整清洗流程代码直接跑一遍终端输出如下能看到数据是怎么一步一步变干净的截图里依次是清洗前各类空值统计、去重后 10 条变 9 条、金额列转成 float64 / 日期转成 datetime64、补完后空值全部归零最后是 9 条干干净净的账单。七、清洗后的检查洗完了不能直接就拿去分析得验一验干不干净。三查原则一查类型对不对df.info()看看每列的类型是不是你想要的——金额是数字、日期是 datetime、分类是字符串或者 category。二查还有没有空值df.isnull().sum()全部是0就说明没空值了。三查肉眼看几行df.head(10)就直接打印前10行用眼睛扫一遍有时候明显的问题一眼就能看出来。八、新手最容易踩的三个坑坑1操作完忘了赋值# ❌ 错的——dropna 返回了新的 DataFrame但你没接住df.dropna()# ✅ 对的——赋值回去dfdf.dropna()# ✅ 或者用 inplacedf.dropna(inplaceTrue)Pandas 里绝大多数操作都是返回新对象不改变原数据。新手经常写完df.dropna()就以为搞定了结果后面一看原数据一点没变。坑2清洗顺序搞错了先去重还是先补空这个顺序很重要。举个例子两行数据几乎一样但其中一行某个列是空的。如果你先补空这两行就变得完全一样了去重的时候会删掉一条。但如果你先去重空的那行可能就被保留下来了补空之后数据还是一条。一般建议先去重 → 再类型转换 → 最后补空值。原因很简单重复的行处理了也是白处理先干掉省得后面白费功夫。类型转换可能会产生新的空值errorscoerce所以补空放在最后。坑3类型转换失败不知道怎么办# ❌ 如果数据里有奇怪的字符会直接报错df[金额].astype(float)# ✅ 用 to_numeric errorscoerce转不了的变空值后面再处理df[金额]pd.to_numeric(df[金额],errorscoerce)真实数据里什么妖魔鬼怪都有——--、待定、N/A、甚至空格。用errorscoerce先统一转成空值再按缺失值的思路处理就稳了。九、小结一下今天这篇讲了数据清洗的四大类问题问题类型怎么发现怎么处理缺失值isnull().sum()删除dropna()/ 填充fillna()/ 按列分别填重复值duplicated().sum()drop_duplicates()/ 按指定列去重类型不对dtypes/info()astype()/pd.to_numeric()/pd.to_datetime()字符串乱肉眼看 / 去重时发现str.strip()/str.replace()/str.lower()/ 分列记住一个口诀先去重再转类型最后补空值。数据清洗这东西说难不难就是琐碎。但这一步做扎实了后面的分析才能靠谱。就像做饭——菜洗干净了怎么炒都不会太差。下一篇我们讲分组统计——groupby 怎么用怎么按类别算出每一类花了多少钱。梅雅达编程工作室 · Python数据实战系列第7篇清洗看着琐碎但数据干不干净决定后面的分析靠不靠谱。这一步值得多花点时间。
返回列表