第 3.1 节 核心知识点#
预计学习时长: 40 分钟
本节目标:
- 会先体检再动手,知道一张表缺了多少值、缺在哪;
- 会用
fillna()填充、dropna()删除缺失行;- 会删重复行,能指定按哪几列判断重复;
- 会批量重命名列名;
- 会用
replace()改掉异常取值;- 会用
astype()/to_numeric()/to_datetime()转类型,并且知道转失败了怎么办。
本课程使用的 Pandas 版本是
'3.1.0'
脏数据并不会报错#
面对一份脏数据 Pandas 并不会抛异常,最终它只会给你一个错的结果。如果你一开始没有认真检查数据,那么最终可能会带来不小的差错。
比如「金额」这一列里有一格是字符串 "未知":
import pandas as pd
data = {
"订单号": [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008],
"下单日期": ["2024-01-05", "2024-01-08", "2024-01-12", "2024-02-03",
"2024-02-15", "2024-03-02", "2024-03-20", "2024-04-08"],
"城市": ["北京", "上海", "北京", "广州", "上海", "北京", "深圳", "广州"],
"商品": ["手机", "电脑", "耳机", "手机", "键盘", "显示器", "耳机", "手机"],
"销量": [2, 1, 3, 2, 5, 1, 4, 2],
"单价": [3999.0, 7999.0, 599.0, 3999.0, 299.0, 1299.0, 599.0, 3999.0],
"金额": [7998.0, 7999.0, 1797.0, 7998.0, 1495.0, 1299.0, 2396.0, 7998.0],
"客户评分": [4.5, 4.0, 4.8, 3.9, 4.2, 4.6, 4.1, 4.9],
}
df = pd.DataFrame(data)这一章我们造一张脏表来练手:
dirty = df.copy()
dirty.loc[1, "金额"] = None # 第 2 行的金额缺失
dirty.loc[5, "客户评分"] = None # 第 6 行的评分缺失
dirty.loc[2, "商品"] = "未知" # 第 3 行的商品是脏值
dirty = pd.concat([dirty, dirty.iloc[[0]]], ignore_index=False) # 重复录了一条
print(dirty) 订单号 下单日期 城市 商品 销量 单价 金额 客户评分
0 1001 2024-01-05 北京 手机 2 3999.0 7998.0 4.5
1 1002 2024-01-08 上海 电脑 1 7999.0 NaN 4.0
2 1003 2024-01-12 北京 未知 3 599.0 1797.0 4.8
3 1004 2024-02-03 广州 手机 2 3999.0 7998.0 3.9
4 1005 2024-02-15 上海 键盘 5 299.0 1495.0 4.2
5 1006 2024-03-02 北京 显示器 1 1299.0 1299.0 NaN
6 1007 2024-03-20 深圳 耳机 4 599.0 2396.0 4.1
7 1008 2024-04-08 广州 手机 2 3999.0 7998.0 4.9
0 1001 2024-01-05 北京 手机 2 3999.0 7998.0 4.5注意最后一行:索引又是 0 了,因为 ignore_index=False 让 Pandas 重新排了号。如果 ignore_index=True 则索引将会变成 8
下面,我们用5个知识点,一步步来把这个脏数据洗干净。
知识点 1:处理缺失值#
第1步:查看哪里缺了多少#
print(dirty.isna().sum())输出:
订单号 0
下单日期 0
城市 0
商品 0
销量 0
单价 0
金额 1
客户评分 1
dtype: int64这张表 9 行 8 列,一共 72 个格子,其中 2 个是空的。
再看整体情况:
print(dirty.isna().sum().sum()) # 总共缺了几个:2,即对上面的结果再求和
print(dirty.isna().any()) # 每一列有没有缺失
print(dirty.isna().any().any()) # 整体有没有缺失值:True输出(每一列有没有缺失):
订单号 False
下单日期 False
城市 False
商品 False
销量 False
单价 False
金额 True
客户评分 True
dtype: bool上面的输出结果告诉我们,“金额”和“客户评分”这两列有缺失值。
isna()和notna()是一对isna()是“有没有空”,返回 True/False;notna()是“有没有值”,正好相反。dirty.isna() # True 表示这里缺了 dirty.notna() # True 表示这里有值最常见的用法是只要有值的行:
dirty[dirty.notna().all(axis=1)] # 所有格子都有值的行 订单号 下单日期 城市 商品 销量 单价 金额 客户评分 0 1001 2024-01-05 北京 手机 2 3999.0 7998.0 4.5 2 1003 2024-01-12 北京 未知 3 599.0 1797.0 4.8 3 1004 2024-02-03 广州 手机 2 3999.0 7998.0 3.9 4 1005 2024-02-15 上海 键盘 5 299.0 1495.0 4.2 6 1007 2024-03-20 深圳 耳机 4 599.0 2396.0 4.1 7 1008 2024-04-08 广州 手机 2 3999.0 7998.0 4.9 0 1001 2024-01-05 北京 手机 2 3999.0 7998.0 4.5第1、5行没了。