前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python数据科学手册(六)【Pandas 处理丢失的数据】

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

作者头像
用户2936342
发布2018-08-27 14:00:04
2.2K0
发布2018-08-27 14:00:04
举报
文章被收录于专栏:nummynummy

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

处理机制的权衡

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

  • 使用掩码全局的指明丢失了哪些数据
  • 使用哨兵值直接替换丢失的值 上述都两种方法各有弊利,使用掩码需要提供一个格外的布尔值数组,占用更多的空间;使用哨兵则在计算时需要更多的时间。

Pandas中的数据丢失

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

None代替丢失值

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

代码语言:javascript
复制
import numpy as np
import pandas as pd
vals1 = np.array([1, None, 3, 4])

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

代码语言:javascript
复制
for dtype in ['object', 'int']:
    print("dtype =", dtype)
    %timeit np.arange(1E6, dtype=dtype).sum()
    print()

结果如下:

代码语言:javascript
复制
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,它时一种特殊的浮点型数据,可以被所有的系统识别。

代码语言:javascript
复制
vals2 = np.array([1, np.nan, 3, 4]) 

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

代码语言:javascript
复制
1 + np.nan   # nan
0 *  np.nan  # nan

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

代码语言:javascript
复制
vals2.sum(), vals2.min(), vals2.max()
# (nan, nan, nan)

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

代码语言:javascript
复制
np.nansum(vals2), np.nanmin(vals2), np.nanmax(vals2)

Pandas中的None和NaN

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

代码语言:javascript
复制
pd.Series([1, np.nan, 2, None])

结果为:

代码语言:javascript
复制
0    1.0
1    NaN
2    2.0
3    NaN
dtype: float64

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

代码语言:javascript
复制
x = pd.Series(range(2), dtype=int)
x[0] = None

针对Null值的操作

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

  • isnull():用于创建掩码数组
  • notnull():isnull()的反操作
  • dropna(): 返回过滤后的数据
  • fillna(): 返回填充后的数据

检测null值

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

代码语言:javascript
复制
data = pd.Series([1, np.nan, 'hello', None])
data.isnull()

结果如下:

代码语言:javascript
复制
0    False
1     True
2    False
3     True
dtype: bool

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

代码语言:javascript
复制
data[data.notnull()]

删除null值

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

代码语言:javascript
复制
data.dropna()

再看下DataFrame的情况:

代码语言:javascript
复制
df = pd.DataFrame([[1,      np.nan, 2],
                   [2,      3,      5],
                   [np.nan, 4,      6]])

image.png

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

代码语言:javascript
复制
df.dropna()

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

代码语言:javascript
复制
df.dropna(axis='columns')

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

代码语言:javascript
复制
df[3] = np.nan
df.dropna(axis='columns', how='all')

image.png

如果需要进一步的控制,可以通过thresh来指定最少保留多少个非NA值。

代码语言:javascript
复制
df.dropna(axis='rows', thresh=3)

填充null值

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

代码语言:javascript
复制
data = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))

输出为

代码语言:javascript
复制
a    1.0
b    NaN
c    2.0
d    NaN
e    3.0
dtype: float64

将上面的NA填充为0:

代码语言:javascript
复制
data.fillna(0)

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

代码语言:javascript
复制
# forward-fill
data.fillna(method='ffill')

结果为

代码语言:javascript
复制
a    1.0
b    1.0
c    2.0
d    2.0
e    3.0
dtype: float64

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

代码语言:javascript
复制
# back-fill
data.fillna(method='bfill')

结果为:

代码语言:javascript
复制
a    1.0
b    2.0
c    2.0
d    3.0
e    3.0
dtype: float64

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

代码语言:javascript
复制
df.fillna(method='ffill', axis=1)

结果为:

image.png

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.09.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 处理机制的权衡
  • Pandas中的数据丢失
    • None代替丢失值
      • NaN 代替丢失值
        • Pandas中的None和NaN
        • 针对Null值的操作
          • 检测null值
            • 删除null值
              • 填充null值
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档