手把手教你用pandas处理缺失值

2021年09月15日 阅读数:1
这篇文章主要向大家介绍手把手教你用pandas处理缺失值,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

做者:韦斯·麦金尼(Wes McKinney)编程

译者:徐敬一数组

来源:大数据DT(ID:hzdashuju)架构

 

导读:在进行数据分析和建模的过程当中,大量的时间花在数据准备上:加载、清理、转换和从新排列。本文将讨论用于缺失值处理的工具。缺失数据会在不少数据分析应用中出现。pandas的目标之一就是尽量无痛地处理缺失值。

pandas对象的全部描述性统计信息默认状况下是排除缺失值的。   pandas对象中表现缺失值的方式并不完美,可是它对大部分用户来讲是有用的。对于数值型数据,pandas使用浮点值NaN(Not a Number来表示缺失值)。咱们称NaN为容易检测到的标识值:dom

  In :   函数

string_data = pd.Series(['aardvark''artichoke', np.nan, 'avocado'])
string_data
  Out:  
0      aardvark
1     artichoke
2            NaN
3       avocado
dtype: object
    In:  
string_data.isnull()
  Out:  
0     False
1     False
2      True
3     False
dtype: bool

在pandas中,咱们采用了R语言中的编程惯例,将缺失值成为NA,意思是not available(不可用)。在统计学应用中,NA数据能够是不存在的数据或者是存在但不可观察的数据(例如在数据收集过程当中出现了问题)。当清洗数据用于分析时,对缺失数据自己进行分析以肯定数据收集问题或数据丢失致使的数据误差一般很重要。   Python内建的None值在对象数组中也被看成NA处理:  工具

In:    大数据

string_data[0] = None
string_data.isnull()
  Out:  
0      True
1     False
2      True
3     False
dtype: bool
  pandas项目持续改善处理缺失值的内部细节,可是用户API函数,好比pandas. isnull,抽象掉了不少使人厌烦的细节。处理缺失值的相关函数列表以下:  
  • dropna:根据每一个标签的值是不是缺失数据来筛选轴标签,并根据容许丢失的数据量来肯定阈值
  • fillna:用某些值填充缺失的数据或使用插值方法(如“ffill”或“bfill”)。
  • isnull:返回代表哪些值是缺失值的布尔值
  • notnull:isnull的副作用函数

    01 过滤缺失值  spa

有多种过滤缺失值的方法。虽然你可使用pandas.isnull和布尔值索引手动地过滤缺失值,但dropna在过滤缺失值时是很是有用的。在Series上使用dropna,它会返回Series中全部的非空数据及其索引值:  code

In:  orm

from numpy import nan as NA
data = pd.Series([1, NA, 3.5, NA, 7])
data.dropna()
  Out:  
0     1.0
2     3.5
4     7.0
dtype: float64

  上面的例子与下面的代码是等价的:

  In:  

data[data.notnull()]
  Out:  
0     1.0
2     3.5
4     7.0
dtype: float64

  当处理DataFrame对象时,事情会稍微更复杂一点。你可能想要删除所有为NA或包含有NA的行或列。dropna默认状况下会删除包含缺失值的行:  

In:  

data = pd.DataFrame([[1.6.53.], [1., NA, NA]
                     [NA, NA, NA], [NA, 6.53.]])
cleaned = data.dropna()
 
data
  Out:  
   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:  
cleaned
  Out:  
   0     1     2
0  1.0  6.5  3.0

  传入how='all’时,将删除全部值均为NA的行:  

In:  

data.dropna(how='all')
  Out:  
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
3  NaN  6.5  3.0

  若是要用一样的方式去删除列,传入参数axis=1:  

In:  

data[4] = NA
data
  Out:  
     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:  
data.dropna(axis=1, how='all')
  Out:  
     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:  

df = pd.DataFrame(np.random.randn(73))
df.iloc[:41] = NA
df.iloc[:22] = NA
df
  Out:  
          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:  
df.dropna()
  Out:  
         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:  
df.dropna(thresh=2)
  Out:  
         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

    02 补全缺失值  

你有时可能须要以多种方式补全“漏洞”,而不是过滤缺失值(也可能丢弃其余数据)。   大多数状况下,主要使用fillna方法来补全缺失值。调用fillna时,可使用一个常数来替代缺失值:  

In:  

df.fillna(0)
  Out:  
          0         1         2
0 -0.204708  0.000000  0.000000
1 -0.555730  0.000000  0.000000
2  0.092908  0.000000  0.769023
3  1.246435  0.000000 -1.296221
4  0.274992  0.228913  1.352917
5  0.886429 -2.001637 -0.371843
6  1.669025 -0.438570 -0.539741

  在调用fillna时使用字典,你能够为不一样列设定不一样的填充值:

  In:  

df.fillna({10.520})
  Out:  
          0         1         2
0 -0.204708  0.500000  0.000000
1 -0.555730  0.500000  0.000000
2  0.092908  0.500000  0.769023
3  1.246435  0.500000 -1.296221
4  0.274992  0.228913  1.352917
5  0.886429 -2.001637 -0.371843
6  1.669025 -0.438570 -0.539741

  fillna返回的是一个新的对象,但你也能够修改已经存在的对象:

  In:  

_ = df.fillna(0, inplace=True)
df
  Out:  
          0         1         2
0 -0.204708  0.000000  0.000000
1 -0.555730  0.000000  0.000000
2  0.092908  0.000000  0.769023
3  1.246435  0.000000 -1.296221
4  0.274992  0.228913  1.352917
5  0.886429 -2.001637 -0.371843
6  1.669025 -0.438570 -0.539741

  用于重建索引的相同的插值方法也能够用于fillna:

  In:  

df = pd.DataFrame(np.random.randn(63))
df.iloc[2:, 1] = NA
df.iloc[4:, 2] = NA
df
  Out:  
          0         1         2
0  0.476985  3.248944 -1.021228
1 -0.577087  0.124121  0.302614
2  0.523772       NaN  1.343810
3 -0.713544       NaN -2.370232
4 -1.860761       NaN       NaN
5 -1.265934       NaN       NaN
  In:  
df.fillna(method='ffill')
  Out:  
          0         1         2
0  0.476985  3.248944 -1.021228
1 -0.577087  0.124121  0.302614
2  0.523772  0.124121  1.343810
3 -0.713544  0.124121 -2.370232
4 -1.860761  0.124121 -2.370232
5 -1.265934  0.124121 -2.370232
  In:  
df.fillna(method='ffill', limit=2)
  Out:  
          0         1         2
0  0.476985  3.248944 -1.021228
1 -0.577087  0.124121  0.302614
2  0.523772  0.124121  1.343810
3 -0.713544  0.124121 -2.370232
4 -1.860761       NaN -2.370232
5 -1.265934       NaN -2.370232

  使用fillna你能够完成不少带有一点创造性的工做。例如,你能够将Series的平均值或中位数用于填充缺失值:

  In:  

data = pd.Series([1., NA, 3.5, NA, 7])
data.fillna(data.mean())
  Out:  
0     1.000000
1     3.833333
2     3.500000
3     3.833333
4     7.000000
dtype: float64
  如下是fillna的函数参数。  
  • value:标量值或字典型对象用于填充缺失值
  • method:插值方法,若是没有其余参数,默认是'ffill'
  • axis:须要填充的轴,默认axis=0
  • inplace:修改被调用的对象,而不是生成一个备份
  • limit:用于前向或后向填充时最大的填充范围
 

关于做者:韦斯·麦金尼(Wes McKinney)是流行的Python开源数据分析库pandas的创始人。他是一名活跃的演讲者,也是Python数据社区和Apache软件基金会的Python/C++开源开发者。目前他在纽约从事软件架构师工做。

 

本文摘编自利用Python进行数据分析》(原书第2版),经出版方受权发布。