Pandas简明教程:七、Pandas缺失数据的处理(数据清洗基础)


数据清洗的内容其实很丰富,其中最基本的问题就是对一些缺失数据的处理。比如我们常会看到这样的表:

First ScoreSecond ScoreThird Score
010030
1904540
25680
39598

在普遍的办公场景下(尤其是一些重要的表格),通常都有可能是有特殊的情况,那么此时都一定会去手动修改,甚至有时还会特别麻烦(比如银行的某些信息)。但我们在竞赛中,研究中,做项目的过程中对这些数据就可以自由一点,希望能利用经验知识等来对它们进行一定的处理。

本文就从这类问题入手讲解一下在Pandas中如何处理这些数据。

1、缺失数据的类型

据官方文档描述,由于在Python中None就是默认的空值类型,因此它首先就会被当作缺失数据处理。

其次Nan (not a number)也是常见的空值或者异常数据类型。

同时,官网说道:+-inf也可以被视作缺失数据,此时需要加设一句:

pandas.options.mode.use_inf_as_na = True

比如上面的数据如果以逗号分隔存入csv文件,再读取出来时是这样:

df = pd.read_csv(r".\test_nan.csv") # 数据存在该文件中

df
   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0           NaN
1           1          90.0            45.0          40.0
2           2           NaN            56.0          80.0
3           3          95.0             NaN          98.0

这里显示的第一列是Index,第二列Unnamed:0是由于这一个位置是空,于是被自动命名为"未命名"表头。而这里我们能清楚地看到,表中的空行已经被显示为NaN

不过要注意的是,此时如果csv文件中这些空值位置是空格或者Tab的话,它会被识别为’ ‘或者’ '。如果不明白就复制引号中的内容,再粘贴到word里面自然就清楚了。

2、定位缺失数据

Pandas中提供了判断表中数据是否为缺失数据的方法isnull:

df.isnull()

   Unnamed: 0  First Score    Second Score    Third Score
0       False         False           False          True
1       False         False           False         False
2       False          True           False         False
3       False         False            True         False

这里可以看到,所有NaN的位置全部变成了True。但光是这样其实还远不够,尤其当数据量较大时,我们其实更想的是如果准确地定位这些数据,再想办法对其进行修改。

当然我们常规的思路是想直接定位到它的行列值上,这样就最方便,但Pandas并没有提供这样的一种方法,非常可惜。于是我们只能选择退而求其次的方案。

首先,我们可以先简单统计一下上哪些列有空值:

df.isnull().sum()

Unnamed: 0        0
First Score       1
 Second Score     1
 Third Score      1
dtype: int64

这个原理就很简单了,由于df.isnull()函数返回的表中每列全是Bool类型,而sum()是针对数值的操作,默认就将TureFalse转为1和0。那么对每列数据求和自然就统计出了缺失的数据总量。

其次,可以考虑直接从DataFrame的值入手,获取缺失数据在其数据主体中所在的位置。

np.argwhere(np.isnan(df.values))

array([[0, 3],
       [2, 1],
       [3, 2]], dtype=int64)

%timeit np.argwhere(np.isnan(df.values))
53.8 µs ± 68.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

这里是借助Numpy中的定位函数,也比较简单,运行的时间也没有想象中那么慢。

此时返回的数组中,第一个元素就是行数,第二个元素就是列所在的位置(也从0开始),那么也很容易找到它们对应的列名:

for i,j in np.argwhere(np.isnan(df.values)):
    print('The',j,'th Column name:',df.iloc[:,j].name)

The 3 th Column name:  Third Score
The 1 th Column name: First Score 
The 2 th Column name:  Second Score 

当然,还有更为高明的方法,可以参考Pandas缺失数据最快定位方式(极少代码快速实现,打死不用循环!!!)

3、修改定位数据

能够精准定位数据,自然也就可以对其进行修改了。最简单的方式自然是给出每个位置应有的值,比如:

df.iloc[2, 1] = 32

当然,这种方式与手动修改无异。我们想要看的是一些简单暴力而又常用的方法。

4、批量修改缺失数据
  • fillna()

比如我想将所有异常数据用一种夸张的形式填充:

df.fillna("!*#^@")

   Unnamed: 0 First Score   Second Score   Third Score
0           0          100             30        !*#^@
1           1           90             45           40
2           2        !*#^@             56           80
3           3           95          !*#^@           98

那么自然地,也可以用一些固定的数值来填充,比如:

df.fillna(-1)

   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0          -1.0
1           1          90.0            45.0          40.0
2           2          -1.0            56.0          80.0
3           3          95.0            -1.0          98.0

这里注意到,fillna()中可以填充的类型是任意的,只要可以作为数据的东西都可以放进去,甚至包括Pandas的object. 这里就不再赘述,其实不用看官方文档也能很容易试出来。

  • 用前或者后(同一列的上一行或下一行)的数据填充:
df.fillna(method='pad')
Out[154]: 
   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0           NaN
1           1          90.0            45.0          40.0
2           2          90.0            56.0          80.0
3           3          95.0            56.0          98.0

df.fillna(method='bfill')
Out[155]: 
   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0          40.0
1           1          90.0            45.0          40.0
2           2          95.0            56.0          80.0
3           3          95.0             NaN          98.0

另外还可对填充次数进行限制,比如只允许填充一次:

df.fillna(method='bfill',limit=1)

这里由于每列数据只有一个空值,因此与上面的代码结果无异。

5、数据修复的利器–插值法(interpolate

可以看到上面缺失的数据都是数值,那么此时我们可以用插值的方式来处理,这种方式尤其在数据本身平稳并且量较充足的时候非常有用。同时也很自然地想到,这种操作对于我们参加数据挖掘竞赛非常有利!

df.interpolate(method='linear')

   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0           NaN
1           1          90.0            45.0          40.0
2           2          92.5            56.0          80.0
3           3          95.0            56.0          98.0

这里可以看到,多数空值都被填充了。它的原理是对现有的点进行线性插值,从而达到数据填充的目的。

另外,细心的同学应该也发现了,这里第一行最后一列数据并未被修改,这是因为默认的插值法是向前插值(即向下面的行进行插值),那么这里稍作修改即可:

df.interpolate(method='linear',limit_direction='backward')
Out[166]: 
   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0          40.0
1           1          90.0            45.0          40.0
2           2          92.5            56.0          80.0
3           3          95.0             NaN          98.0

如果上下都想用,就用两次即可:

df.interpolate(method='linear',limit_direction='backward').interpolate(method='linear',limit_direction='forward')

   Unnamed: 0  First Score    Second Score    Third Score
0           0         100.0            30.0          40.0
1           1          90.0            45.0          40.0
2           2          92.5            56.0          80.0
3           3          95.0            56.0          98.0

注:Pandas在实现这类方法时实际上是调用的scipy的库,因此需要提前将scipy装好。

当然,插值的方法有很多,目前该方法提供的选择如下:

  • ‘linear’: 线性插值
  • ‘index’, ‘values’: 用索引值直接填充.
  • ‘nearest’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’, ‘spline’, ‘barycentric’, ‘polynomial’:
    • 其中: ‘polynomial’ ,‘spline’ 需要设置阶数,如: df.interpolate(method='polynomial', order=5).
  • ‘krogh’, ‘piecewise_polynomial’, ‘spline’, ‘pchip’, ‘akima’: scipy中对应的方法(名称一致)
  • ‘from_derivatives’: 采用方法scipy.interpolate.BPoly.from_derivatives

关于上述所有方法的说明可以直接参考scipy的文档或者用户说明

本系列教程教程完整目录:

一、Pandas简介与安装

二、Pandas基本数据结构-DataFrame与Series

三、Pandas文件读写

四、Pandas数据索引方式

五、Pandas简单统计操作及通用方式

六、Pandas条件查询

七、Pandas缺失数据的处理(数据清洗基础)

八、Pandas数据透视表

九、表的合并、连接、拼接(数据聚合基础)

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半个冯博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值