Py学习  »  Python

Python-S02E14Pandas缺失值的处理

一个普普通通简简单单平平凡凡的神 • 5 年前 • 337 次点击  

陪伴学习,一路成长。请一起关注,一起点赞吧!

【要点抢先看】

1.Pandas中缺失值的表征方式及运算处理规则
2.如何发现缺失值
3.如何对缺失值进行丢弃处理
4.如何对缺失值进行填充处理

现实中的数据,往往不如我们在例子中演示的那般干净、整齐,经常会出现数据缺失的现象,今天这一集,我们就来说说Pandas中缺失值的处理方法。

python中采用一种NaN(Not a Number)标签来表示缺失值,NaN本质上是一种浮点数类型:

import pandas as pd
import numpy as np

var = np.array([1, np.nan, 3, 4])
print(var)
print(var.dtype)

[  1.  nan   3.   4.]
float64

运行结果很清楚的表明,NumPy为缺失值选择了一种原生类型的数据类型:浮点型。

nan缺失值类型有一个重要的特性,就是任何数与之运算,其结果都是nan。

import pandas as pd
import numpy as np

var = np.array([1, 2, np.nan, 4])
print(np.nan + 1)
print(np.nan * 5)
print(var.sum())
print(var.max())

nan
nan
nan
nan

当然,如果在NumPy中忽略掉nan缺失值进行一些运算,也是有办法的,NumPy有专门的函数:

import pandas as pd
import numpy as np

var = np.array([1, 2, np.nan, 4])
print(np.nansum(var))
print(np.nanmax(var))
print(np.nanmin(var))

7.0
4.0
1.0

Pandas数据类型对缺失值的处理也是类似的,NaN表示缺失值时,他的类型是浮点数,如果表示缺失对象时,他的类型是object类型。

首先举一个浮点类型缺失值的例子,将整数型Series中的某值设置为缺失型,整个Series将强制变成浮点型:

import pandas as pd
import numpy as np

var = pd.Series([1,2],dtype=int)
print(var)
var[0] = np.nan
print(var)

0    1
1    2
dtype: int32

0    NaN
1    2.0
dtype: float64

表示缺失对象的场景我们也可以举一个例子,如果Series中的数据类型是字符串,由于字符串是object类型,因此将该类型的Series中的某个字符串数据设置为缺失型,整个类型仍是object类型。

import pandas as pd
import numpy as np

var = pd.Series(['aa','bb'])
print(var)
var[0] = np.nan
print(var)

0    aa
1    bb
dtype: object

0    NaN
1     bb
dtype: object

了解了缺失值的基本知识,那重点来了,使用Pandas工具时如何处理缺失值呢?

首先是如何发现缺失值。我们可以用isnull()和notnull()两种方法来发现缺失值。

import pandas as pd
import numpy as np

var = pd.Series(['aa',np.nan,1,np.nan])
print(var.isnull())
print(var.notnull())

0    False
1     True
2    False
3     True
dtype: bool

0     True
1    False
2     True
3    False
dtype: bool

这两种方法,返回的都是布尔型的掩码数据,isnull()会在为空的位置上显示True,notnull则正好相反。

这种布尔型掩码数据可以作为一种过滤的工具:

import pandas as pd
import numpy as np

var = pd.Series(['aa',np.nan,1,np.nan])
print(var[var.notnull()])

0    aa
2     1
dtype: object

那么自然,下一步我们就应该讨论如何处理缺失值,最简单的方法是丢弃缺失值

Series数据类型对于缺失值的处理很简单,就是简单的丢弃相应的值:

import pandas as pd
import numpy as np

var = pd.Series(['aa',np.nan,1,np.nan])
print(var.dropna())

0    aa
2     1
dtype: object

但是DataFrame就要复杂一些,他无法简单的单独剔除掉一个缺失值,要么剔除缺失值所在的整行,要么剔除掉整列,默认是剔除行,如果要剔除所在列的话,需要单独设置axis=1的关键字参数。

import pandas as pd
import numpy as np

df = pd.DataFrame([[1,np.nan,2],
                   [2,3,5],
                   [np.nan,4,6]])
print(df)                       #原始df
print(df.dropna())         #丢弃缺失值所在行
print(df.dropna(axis=1))#丢弃缺失值所在列

     0    1  2
0  1.0  NaN  2
1  2.0  3.0  5
2  NaN  4.0  6

     0    1  2
1  2.0  3.0  5

   2
0  2
1  5
2  6

在dropna()函数中还有一个非常重要的参数how,默认how=any,表示此行(或列)只要有一个NaN值,就要删除所在行(或列)。当how=all是表示只有当此行(或列)全部都是NaN值时,才执行此操作。

import pandas as pd
import numpy as np

df = pd.DataFrame([[1,np.nan,2,4],
                   [2,3,5,3],
                   [np.nan,np.nan,np.nan,np.nan]])
print(df)
print(df.dropna(how='any'))
print(df.dropna(how='all'))

     0    1    2    3
0  1.0  NaN  2.0  4.0
1  2.0  3.0  5.0  3.0
2  NaN  NaN  NaN  NaN

     0    1    2    3
1  2.0  3.0  5.0  3.0

     0    1    2    3
0  1.0  NaN  2.0  4.0
1  2.0  3.0  5.0  3.0

当然还有一个更精细的thresh参数控制,他表示留下此行(或列)时,非缺失值最少需要有的个数。

import pandas as pd
import numpy as np

df = pd.DataFrame([[1,np.nan,2,4],
                   [2,np.nan,np.nan,3],
                   [np.nan,np.nan,np.nan,np.nan]])
print(df)
print(df.dropna(thresh=3))

     0   1    2    3
0  1.0 NaN  2.0  4.0
1  2.0 NaN  NaN  3.0
2  NaN NaN  NaN  NaN

     0   1    2    3
0  1.0 NaN  2.0  4.0

我们看到第二行和第三行被剔除了,因为他们的非缺失值个数不足3个

但是,有时候我们并不想因为剔除缺失值而删掉他所在的行,因为这样失去的有用信息就太多了,因此我们还有一种处理方法,那就是填充缺失值。

第一种方法是用指定的值来填充缺失值:

import pandas as pd
import numpy as np

df = pd.DataFrame([[11,np.nan,22,44],
                   [22,np.nan,np.nan,33],
                   [np.nan,np.nan,np.nan,np.nan]])
print(df.fillna(0))

      0    1     2     3
0  11.0  0.0  22.0  44.0
1  22.0  0.0   0.0  33.0
2   0.0  0.0   0.0   0.0

在这个例子中,我们用0填充了所有的缺失值。

还有一种常见的方法,就是用相邻的值进行填充,这在时间序列分析中相当常见,自然,可以用前面相邻的值向后填充,也可以用后面相邻的值向前填充。

import pandas as pd
import numpy as np

data = pd.Series([1,np.nan,2,np.nan,3],index=list('abcde'))
print(data)
print(data.fillna(method='ffill'))
print(data.fillna(method='bfill'))

a    1.0
b    NaN
c    2.0
d    NaN
e    3.0
dtype: float64

a    1.0
b    1.0
c    2.0
d    2.0
e    3.0
dtype: float64

a    1.0
b    2.0
c    2.0
d    3.0
e    3.0
dtype: float64

从结果中我们很容易看懂从前往后填充以及从后往前填充的具体效果。

当然DataFrame数据类型也是同理,当然他还可以指定填充具体是沿着那个方向,下面的例子,我们指定沿着纵轴的方向,从前往后进行填充:

import pandas as pd
import numpy as np

df = pd.DataFrame([[1,np.nan,2,4],
                   [2,3,5,3],
                   [np.nan,5,4,np.nan]])
print(df)
print(df.fillna(method='ffill', axis=1))

     0    1  2    3
0  1.0  NaN  2  4.0
1  2.0  3.0  5  3.0
2  NaN  5.0  4  NaN

     0    1    2    3
0  1.0  1.0  2.0  4.0
1  2.0  3.0  5.0  3.0
2  NaN  5.0  4.0  4.0

当然,如果从前往后填充,第一个值就是NaN,那自然是没有办法进行填充处理了。

【妹子说】没想到对于缺失值进行处理还有这么多讲究,那看来Pandas对于实际的数据清洗工作确实考虑的非常全面。


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/HmEFv6SK5p
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/10369
 
337 次点击