python进阶我爱编程

Python数据科学手册(六)【Pandas 处理丢失的数据】

2017-09-17  本文已影响114人  nummycode

在很多情况下,有些数据并不是完整的,丢失了部分值,这一节将学习如何处理这些丢失的数据。

处理机制的权衡

常见的处理丢失数据的方法有两种:

Pandas中的数据丢失

Pandas中处理数据丢失的方法受制于Numpy,尽管Numpy提供了掩码机制,但是在存储、计算和代码维护来说,并不划算,所以Pandas使用哨兵机制来处理丢失的数据。Pandas使用NaN或者None来代替丢失的值。

None代替丢失值

第一个被Pandas使用的哨兵值是None, 由于None是Python对象,所以它并不适合所有情况,只能用于数组的类型为对象的情况。

import numpy as np
import pandas as pd
vals1 = np.array([1, None, 3, 4])

对象类型也就意味着数组的元素内容为Python对象,所以计算速度会大打折扣。

for dtype in ['object', 'int']:
    print("dtype =", dtype)
    %timeit np.arange(1E6, dtype=dtype).sum()
    print()

结果如下:

dtype = object
10 loops, best of 3: 78.2 ms per loop

dtype = int
100 loops, best of 3: 3.06 ms per loop

使用None会导致一些聚合操作,比如sum()min()会报错。

NaN 代替丢失值

另外一中哨兵是使用NaN,它时一种特殊的浮点型数据,可以被所有的系统识别。

vals2 = np.array([1, np.nan, 3, 4]) 

不管什么操作,只要有NaN,结果都为NaN:

1 + np.nan   # nan
0 *  np.nan  # nan

这也就意味着所有的聚合操作都能进行,但结果都是NaN

vals2.sum(), vals2.min(), vals2.max()
# (nan, nan, nan)

Numpy还提供了一些函数用于聚合运算,可以忽略掉丢失的数据:

np.nansum(vals2), np.nanmin(vals2), np.nanmax(vals2)

Pandas中的None和NaN

None和NaN在Pandas有其独特的地位,Pandas同时支持它们,并可以相互转换。

pd.Series([1, np.nan, 2, None])

结果为:

0    1.0
1    NaN
2    2.0
3    NaN
dtype: float64

对于某些不支持哨兵值的数据类型,当遇到NA值时Pandas会自动转型,例如下面的例子,integer会转型为浮点型:

x = pd.Series(range(2), dtype=int)
x[0] = None

针对Null值的操作

由上可知,Pandas将None和NaN视为可交换的,它们都可以用来指示丢失的数据。Pandas提供了一些便利函数用于处理这个数据。

检测null值

Pandas提供的isnull()和notnull()函数可用于检查null值,它们都会返回一个布尔值数组:

data = pd.Series([1, np.nan, 'hello', None])
data.isnull()

结果如下:

0    False
1     True
2    False
3     True
dtype: bool

前面说过,布尔值掩码可直接用于索引对象:

data[data.notnull()]

删除null值

使用dropna()来删除NA值,使用fillna()填充NA值。

data.dropna()

再看下DataFrame的情况:

df = pd.DataFrame([[1,      np.nan, 2],
                   [2,      3,      5],
                   [np.nan, 4,      6]])
image.png

从DataFrame中无法删除单个的值,只能删除整行或者整列数据。

df.dropna()

如果axis为1,则删除出现NA的列:

df.dropna(axis='columns')

但是这种处理方式还是过于粗暴,有没有更为精细的控制呢?Pandas提供了更为精细的控制,通过参数howthresh来控制。
how的默认值为any, 也就是说任意行或者列只要出现NA值就删除,如果修改为all,则只有所有值都为NA的时候才会删除。

df[3] = np.nan
df.dropna(axis='columns', how='all')
image.png
如果需要进一步的控制,可以通过thresh来指定最少保留多少个非NA值。
df.dropna(axis='rows', thresh=3)

填充null值

有些时候,并不想抛弃NA值,而想填充成其他的值,Pandas提供了fillna()方法:

data = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))

输出为

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

将上面的NA填充为0:

data.fillna(0)

也可以使用前一个值来填充:

# forward-fill
data.fillna(method='ffill')

结果为

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

还可以使用后一个值来填充:

# back-fill
data.fillna(method='bfill')

结果为:

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

对于DataFrame,可以指定填充的轴:

df.fillna(method='ffill', axis=1)

结果为:

image.png
上一篇下一篇

猜你喜欢

热点阅读