pandas基础--缺失数据处理
pandas含有是数据分析工作变得更快更简单的高级数据结构和操作工具,是基于numpy构建的。
本章节的代码引入pandas约定为:import pandas as pd,另外import numpy as np也会用到。
官方介绍:pandas - Python Data Analysis Library (pydata.org)
7 缺失数据处理
缺失数据是数据分析中的常见现象。pandas使用浮点值NaN(Not a Number)表示浮点和非浮点数组中的缺失数据。它只是一个便于被检测出来的标记而已。python内置的None值也会被当作NA处理。
1 >>> string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
2 >>> string_data
3 0 aardvark
4 1 artichoke
5 2 NaN
6 3 avocado
7 dtype: object
8 >>> string_data.isnull()
9 0 False
10 1 False
11 2 True
12 3 False
13 dtype: bool
14 >>> string_data[0] = None
15 >>> string_data.isnull()
16 0 True
17 1 False
18 2 True
19 3 False
20 dtype: bool
21 >>>
NA处理方法。
方式 | 说明 |
---|---|
dropna | 根据各标签的值中是否存在缺失数据对轴标签进行过滤,可通过阈值调节对缺失值的容忍度,也就是thresh参数,如设置为2,则至少行(列)有两个非NaN值才保留。 |
fillna | 用指定值或插值方法(如ffill或bfill)填充缺失数据 |
isnull | 返回一个含有布尔值的对象,这些布尔值表示哪些值是缺失值NA,该对象的类型和源类型一样 |
notnull | isnull的否定式 |
部分官方说明:
pandas.DataFrame.dropna — pandas 1.3.4 documentation (pydata.org)
pandas.DataFrame.fillna — pandas 1.3.4 documentation (pydata.org)
>>> string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
>>> string_data
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
>>> string_data.dropna()
0 aardvark
1 artichoke
3 avocado
dtype: object
>>> string_data.fillna(value='haha')
0 aardvark
1 artichoke
2 haha
3 avocado
dtype: object
7.1 滤除缺失数据
过滤掉缺失数据的方法有多种,可通过dropna实现。
1 >>> from numpy import nan as NA
2 >>> data = pd.Series([1, NA, 3.5, NA, 7])
3 >>> data.dropna()
4 0 1.0
5 2 3.5
6 4 7.0
7 dtype: float64
8 >>> data[data.isnull()]
9 1 NaN
10 3 NaN
11 dtype: float64
12 >>> data[data.notnull()]
13 0 1.0
14 2 3.5
15 4 7.0
16 dtype: float64
对于DataFrame,可能希望丢弃全NA或含有NA的行或列。
1 >>> data = pd.DataFrame([[1, 1.6, 3], [1, NA, NA], [NA, NA, NA], [NA, 6.5, 3]])
2 >>> data
3 0 1 2
4 0 1.0 1.6 3.0
5 1 1.0 NaN NaN
6 2 NaN NaN NaN
7 3 NaN 6.5 3.0
8 >>>
9 >>> cleaned = data.dropna() #默认丢弃任何含有缺失值的行
10 >>> cleaned
11 0 1 2
12 0 1.0 1.6 3.0
13 >>> data.dropna(how='all') #只丢弃全为NA的行
14 0 1 2
15 0 1.0 1.6 3.0
16 1 1.0 NaN NaN
17 3 NaN 6.5 3.0
18 >>> data[4] = NA
19 >>> data
20 0 1 2 4
21 0 1.0 1.6 3.0 NaN
22 1 1.0 NaN NaN NaN
23 2 NaN NaN NaN NaN
24 3 NaN 6.5 3.0 NaN
25 >>> data.dropna(axis=1, how='all') #丢弃列,且列的所有值为NaN才丢弃
26 0 1 2
27 0 1.0 1.6 3.0
28 1 1.0 NaN NaN
29 2 NaN NaN NaN
30 3 NaN 6.5 3.0
31 >>>
另一个滤除DataFrame行的问题涉及到时间序列数据。如果只想留下一部分观测数据,可以用thresh参数实现。
1 >>> df = pd.DataFrame(np.random.randn(7, 3))
2 >>> df
3 0 1 2
4 0 0.752301 1.360969 -0.474561
5 1 0.466749 0.563536 1.978575
6 2 0.223606 0.414722 0.094315
7 3 -1.687511 -0.116227 0.442363
8 4 0.705580 -0.131169 -0.868425
9 5 -0.158964 -0.164512 -0.937150
10 6 -0.281537 -1.579942 -0.562886
11 >>> df.loc[:4, 1] = NA
12 >>> df.loc[:2, 2] = NA
13 >>> df
14 0 1 2
15 0 0.752301 NaN NaN
16 1 0.466749 NaN NaN
17 2 0.223606 NaN NaN
18 3 -1.687511 NaN 0.442363
19 4 0.705580 NaN -0.868425
20 5 -0.158964 -0.164512 -0.937150
21 6 -0.281537 -1.579942 -0.562886
>>> df.dropna(thresh=2) #行至少有两个非NaN值才保留
0 1 2
3 -0.845402 NaN -0.037411
4 -0.563560 NaN -0.992985
5 0.227253 -1.649384 -0.754437
6 1.090384 0.980745 0.661543
7.2 填充缺失数据
fillna方法可实现将缺失值替换为一个常数值。
官方文档:pandas.DataFrame.fillna — pandas 1.3.4 documentation (pydata.org)
1 >>> df
2 0 1 2
3 0 0.752301 NaN NaN
4 1 0.466749 NaN NaN
5 2 0.223606 NaN NaN
6 3 -1.687511 NaN 0.442363
7 4 0.705580 NaN -0.868425
8 5 -0.158964 -0.164512 -0.937150
9 6 -0.281537 -1.579942 -0.562886
10 >>> df.fillna(0)
11 0 1 2
12 0 0.752301 0.000000 0.000000
13 1 0.466749 0.000000 0.000000
14 2 0.223606 0.000000 0.000000
15 3 -1.687511 0.000000 0.442363
16 4 0.705580 0.000000 -0.868425
17 5 -0.158964 -0.164512 -0.937150
18 6 -0.281537 -1.579942 -0.562886
19 >>> df.fillna({1:0.5, 3:-1}) #第1列的NA替换为0.5,第3列的NA替换为-1
20 0 1 2
21 0 0.752301 0.500000 NaN
22 1 0.466749 0.500000 NaN
23 2 0.223606 0.500000 NaN
24 3 -1.687511 0.500000 0.442363
25 4 0.705580 0.500000 -0.868425
26 5 -0.158964 -0.164512 -0.937150
27 6 -0.281537 -1.579942 -0.562886
28 >>>
fillna默认会返回新对象。但也可以对现有对象进行就地修改。
1 >>> _ = df.fillna(0, inplace=True)
2 >>> df
3 0 1 2
4 0 0.752301 0.000000 0.000000
5 1 0.466749 0.000000 0.000000
6 2 0.223606 0.000000 0.000000
7 3 -1.687511 0.000000 0.442363
8 4 0.705580 0.000000 -0.868425
9 5 -0.158964 -0.164512 -0.937150
10 6 -0.281537 -1.579942 -0.562886
11 >>>
对reindex有效的插值方法也可以用于fillna。
1 >>> df = pd.DataFrame(np.random.randn(6, 3))
2 >>> df.loc[2:, 1] = NA
3 >>> df.loc[4:, 2] = NA
4 >>> df
5 0 1 2
6 0 -1.433489 0.162951 -0.664600
7 1 0.033722 -0.478252 0.480072
8 2 -0.000977 NaN -1.555649
9 3 -0.947501 NaN 0.089918
10 4 1.360481 NaN NaN
11 5 -0.966030 NaN NaN
12 >>> df.fillna(method='ffill')
13 0 1 2
14 0 -1.433489 0.162951 -0.664600
15 1 0.033722 -0.478252 0.480072
16 2 -0.000977 -0.478252 -1.555649
17 3 -0.947501 -0.478252 0.089918
18 4 1.360481 -0.478252 0.089918
19 5 -0.966030 -0.478252 0.089918
20 >>> df.fillna(method='ffill', limit=2)
21 0 1 2
22 0 -1.433489 0.162951 -0.664600
23 1 0.033722 -0.478252 0.480072
24 2 -0.000977 -0.478252 -1.555649
25 3 -0.947501 -0.478252 0.089918
26 4 1.360481 NaN 0.089918
27 5 -0.966030 NaN 0.089918
下表是fillna的参数参考。
参数 | 说明 |
---|---|
value | 用于填充缺失值的标量值或字典对象 |
method | 插值方式,如果函数调用时未指定其他参数的话,默认为“ffill” |
axis | 带填充的轴,默认为axis=0 |
limit | (对于向前或先后填充)可以连续填充的最大数量 |