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

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

处理机制的权衡

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

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

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提供了一些便利函数用于处理这个数据。

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

检测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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

nummy

152 篇文章25 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏犀利豆的技术空间

Redis 的基础数据结构(二) 整数集合、跳跃表、压缩列表

上篇文章写了 Redis 基础数据结构的可变字符串、链表、字典。大家可以点击链接查看。今天我们继续研究 Redis 的基础数据结构。

983
来自专栏逍遥剑客的游戏开发

C++的反射和序列化

1542
来自专栏对角另一面

lodash源码分析之数组的差集

本文为读 lodash 源码的第十七篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

1254
来自专栏difcareer的技术笔记

JNI实现源码分析【四 函数调用】正文0x01:dvmCallMethodV0x02:nativeFunc0x03: 何时赋值

有了前面的铺垫,终于可以说说虚拟机是如何调用JNI方法的了。JNI方法,对应Java中的native方法,所以我们跟踪对Native方法的处理即可。

984
来自专栏北京马哥教育

十分钟完成Bash 脚本进阶!列举Bash经典用法及其案例

前言:在linux中,Bash脚本是很基础的知识,大家可能一听脚本感觉很高大上,像小编当初刚开始学一样,感觉会写脚本的都是大神。虽然复杂的脚本是很烧脑,但是,当...

1483
来自专栏拭心的安卓进阶之路

并发编程4:Java 阻塞队列源码分析(上)

上篇文章 并发编程3:线程池的使用与执行流程 中我们了解到,线程池中需要使用阻塞队列来保存待执行的任务。这篇文章我们来详细了解下 Java 中的阻塞队列究竟是什...

4039
来自专栏醒者呆

掌握一门语言Go

摘要:Go语言的优势不必多说,通过本篇文章,让我们花时间来掌握一门外语,Let's Go! 关键字:Go语言,闭包,基本语法,函数与方法,指针,slic...

4249
来自专栏PHP在线

正则表达式中的子组模式

作者:西瓜玩偶(racnil070512 at hotmail dot com) 一、基础知识 在PCRE正则表达式中,我们可以利用圆括号定义一个子组,我们...

39812
来自专栏HTML5学堂

2015.12.23 HTML5真题练习

HTML5学堂:每天一道题,强壮程序员!今日主要涉及12.22日关于作用域、预编译执行知识的题目解答,以及一道涉及逗号运算符和for循环的题目。 HTML5真题...

2685
来自专栏李海辰的专栏

Unity引擎资源管理代码分析 ( 2 )

上一篇《Unity 引擎资源管理代码分析 ( 1 ) 》讲解了 Unity 引擎资源管理代码的类型设计架构和 Resources.Load 接口的实现,本文将...

8054

扫码关注云+社区

领取腾讯云代金券