在许多数据分析工作中,缺失数据是经常发生的。Pandas 的目标之一就是尽量轻松地处理缺失数据。例如,Pandas 对象的所有描述性统计默认都不包括缺失数据。
缺失数据在 Pandas 中呈现的方式有些不完美,但对于大多数用户可以保证功能正常。对于数值数据,Pandas 使用浮点值 NaN(Not a Number)表示缺失数据。我们称其为哨兵值,可以方便的检测出来:
In [10]: string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
In [11]: string_data
Out[11]:
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
In [12]: string_data.isnull()
Out[12]:
0 False
1 False
2 True
3 False
dtype: bool
在 Pandas 中,我们采用了 R 语言中的惯用法,即将缺失值表示为 NA,它表示不可用 not available。在统计应用中,NA 数据可能是不存在的数据或者虽然存在,但是没有观察到(例如,数据采集中发生了问题)。当进行数据清洗以进行分析时,最好直接对缺失数据进行分析,以判断数据采集的问题或缺失数据可能导致的偏差。
Python 内置的 None 值在对象数组中也可以作为 NA:
In [13]: string_data[0] = None
In [14]: string_data.isnull()
Out[14]:
0 True
1 False
2 True
3 False
dtype: bool
Pandas 项目中还在不断优化内部细节以更好处理缺失数据,像用户 API 功能,例如 pandas.isnull,去除了许多恼人的细节。表列出了一些关于缺失数据处理的函数。
| 方法 | 说明 |
| dropna | 根据各标签的值中是否存在缺失数据对轴标签进行过滤,可通过阈值调节对缺失值的容忍度 |
| fillna | 用指定值和插值方法(ffill 或 bfill)填充缺失数据 |
| isnull | 返回一个含有布尔值的对象,这些布尔值表示哪些值是缺失值 /NA,对象的类型与源类型一样 |
| notnull | isnull 的否定式 |
过滤掉缺失数据的办法有很多种。你可以通过 pandas.isnull 或布尔索引的手工方法,但 dropna 可能会更实用一些。对于一个 Series,dropna 返回一个仅含非空数据和索引值的 Series:
In [15]: from numpy import nan as NA
In [16]: data = pd.Series([1, NA, 3.5, NA, 7])
In [17]: data.dropna()
Out[17]:
0 1.0
2 3.5
4 7.0
dtype: float64
这等价于:
In [18]: data[data.notnull()]
Out[18]:
0 1.0
2 3.5
4 7.0
dtype: float64
而对于 DataFrame 对象,事情就有点复杂了。你可能希望丢弃全 NA 或含有 NA 的行或列。dropna 默认丢弃任何含有缺失值的行:
In [19]: data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
……: [NA, NA, NA], [NA, 6.5, 3.]])
In [20]: cleaned = data.dropna()
In [21]: data
Out[21]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
In [22]: cleaned
Out[22]:
0 1 2
0 1.0 6.5 3.0
传入 how=’all’将只丢弃全为 NA 的那些行:
In [23]: data.dropna(how='all')
Out[23]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
用这种方式丢弃列,只需传入 axis= 1 即可:
In [24]: data[4] = NA
In [25]: data
Out[25]:
0 1 2 4
0 1.0 6.5 3.0 NaN
1 1.0 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.5 3.0 NaN
In [26]: data.dropna(axis=1, how='all')
Out[26]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
另一个滤除 DataFrame 行的问题涉及时间序列数据。假设你只想留下一部分观测数据,可以用 thresh 参数实现此目的:
In [27]: df = pd.DataFrame(np.random.randn(7, 3))
In [28]: df.iloc[:4, 1] = NA
In [29]: df.iloc[:2, 2] = NA
In [30]: df
Out[30]:
0 1 2
0 -0.204708 NaN NaN
1 -0.555730 NaN NaN
2 0.092908 NaN 0.769023
3 1.246435 NaN -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
In [31]: df.dropna()
Out[31]:
0 1 2
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
In [32]: df.dropna(thresh=2)
Out[32]:
0 1 2
2 0.092908 NaN 0.769023
3 1.246435 NaN -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
你可能不想滤除缺失数据(有可能会丢弃跟它有关的其他数据),而是希望通过其他方式填补那些“空洞”。对于大多数情况而言,fillna 方法是最主要的函数。通过一个常数调用 fillna 就会将缺失值替换为那个常数值:
[版权声明] :本文文字、代码及图片版权归原作者所有,任何媒体、网站或个人未经本网协议授权不得采集、整理、转载或以其他方式复制发表。已经本站协议授权的媒体、网站,在使用时必须注明“稿件来源:学研谷”。