返回首页

Roadmap
更新于 2026年10月30日 全文 409 字未阅读

第 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行没了。

阅读 --