Python中如何使用Pandas处理缺失的数据

在许多数据分析工作中,缺失数据是经常发生的。pandas的目标之一就是尽量轻松地处理缺失数据。例如,pandas对象的所有描述性统计默认都不包括缺失数据。

1.处理缺失数据

缺失数据在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,对象的类型与源类型一样
notnullisnull的否定式

2. 滤除缺失数据

过滤掉缺失数据的办法有很多种。你可以通过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

3. 填充缺失数据

你可能不想滤除缺失数据(有可能会丢弃跟它有关的其他数据),而是希望通过其他方式填补那些“空洞”。对于大多数情况而言,fillna方法是最主要的函数。通过一个常数调用fillna就会将缺失值替换为那个常数值:

  • 发表于 2019-11-22 10:06
  • 阅读 ( 51 )

[版权声明] :本文文字、代码及图片版权归原作者所有,任何媒体、网站或个人未经本网协议授权不得采集、整理、转载或以其他方式复制发表。已经本站协议授权的媒体、网站,在使用时必须注明“稿件来源:学研谷”。

0 条评论

请先 登录 后评论
猜猜我是谁
CSUA -研究生

6
提问
55
回答
27
文章