小白学 Python 数据分析(8):Pandas (七)数据预处理

人生苦短,我用 Python

前文传送门:

小白学 Python 数据分析(1):数据分析基础

小白学 Python 数据分析(2):Pandas (一)概述

小白学 Python 数据分析(3):Pandas (二)数据结构 Series

小白学 Python 数据分析(4):Pandas (三)数据结构 DataFrame

小白学 Python 数据分析(5):Pandas (四)基础操作(1)查看数据

小白学 Python 数据分析(6):Pandas (五)基础操作(2)数据选择

小白学 Python 数据分析(7):Pandas (六)数据导入

引言

上一篇我们介绍了数据导入,在进行分析之前,还有一个比较重要的步骤就是数据的预处理,很多时候,我们导入的数据质量并不高,会有很多不达标的数据。

这就和我们每天做饭是一样的,买回来的菜总归会有一些不太好的部分,我们需要在做饭之前对这些菜做一些预处理,将不好的部分处理掉。

常见的数据问题主要有缺失数据、重复数据以及异常数据这么几种,在开始进行数据分析之前,我们需要先把这部分的数据处理掉。

缺失数据处理

缺失数据其实就是由于某些不为人知的原因导致的部分数据为空,关注点不要放在不为人知的原因是啥上哈,这种原因简直多了去了,任何一位程序员都能举出来无数种例子。

对于这种部分为空的数据我们通常有两种处理方式,一种是直接删除,还有一种是填充某种设定值。

当然,选用哪种方式完全是看具体的业务场景。

首先,第一步当然是把缺失的数据找出来, Pandas 找缺失数据可以使用 info() 这个方法(这里选用的数据源还是前面一篇文章所使用的 Excel ,小编这里简单的随机删除掉几个数据):

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")
print(df)

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

print(df.info())

# 输出结果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 408 entries, 0 to 407
Data columns (total 6 columns):
plantform      408 non-null object
read_num       406 non-null float64
fans_num       408 non-null int64
rank_num       407 non-null float64
like_num       408 non-null int64
create_date    408 non-null datetime64[ns]
dtypes: datetime64[ns](1), float64(2), int64(2), object(1)
memory usage: 19.2+ KB

从结果中可以看到,不为空的行数共计 408 行,而 read_num 这一行为 406 ,说明小编在这一列删掉了 2 个数据,在 rank_num 这一列删掉了 1 个数据。

我们还可以使用另一个更加直观的方式来获取缺失的数据 isnull() ,如果是缺失的值,会返回 True ,如果不是则会返回 False :

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")
print(df.isnull())

# 输出结果
     plantform  read_num  fans_num  rank_num  like_num  create_date
0        False     False     False     False     False        False
1        False      True     False     False     False        False
2        False     False     False     False     False        False
3        False     False     False      True     False        False
4        False     False     False     False     False        False
..         ...       ...       ...       ...       ...          ...
403      False     False     False     False     False        False
404      False     False     False     False     False        False
405      False     False     False     False     False        False
406      False     False     False     False     False        False
407      False     False     False     False     False        False

[408 rows x 6 columns]

使用 isnull() 是比较直观,那么这里存在一个问题,就是好像数据显示不全啊,这种问题小 case ,只需一行代码轻松解决:

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

pd.set_option('display.max_rows', None)
print(df.isnull())

只需要对 pd 的显示设置下最大行数就好,结果稍微有点长,小编就不贴了。

缺失数据删除

我们找到了缺失的数据,接下来就是对这部分数据进行删除操作了, Pandas 同样为我们提供了一个现成的方法 dropna()

dropna() 这个方法会默认删除缺失数据的行,就是这一行只要有缺失数据,整行都会删除:

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df.dropna())

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
5        csdn    2202.0       129       0.0        37 2019-11-22 23:00:01
7        csdn    1621.0        76       0.0        27 2019-11-21 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[405 rows x 6 columns]

可以看到,这里显示的行数只剩 405 行了,其中有 3 行有缺失的数据已经删除了。

在删除缺失行的时候还会有一种情况,就是整行数据全都缺失,我们还可以只删除整行数据全缺失,如果只是有缺失值的数据保留,这时我们可以用到 dropna() 的一个参数 how="any"

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df.dropna(how="any"))

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

因为小编的数据没有整行缺失的,可以看到这里又打印了所有的数据。

当然, dropna() 同时支持各种条件删除,这里篇幅原因小编就不一一列举了,有需要的同学可以访问官方文档查看:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html

缺失数据填充

前面我们介绍了缺失数据的删除,但是数据是很宝贵的,通常情况下肯定不能做简单的删除操作,更多的时候我们是希望能填充我们想要的默认值,这里我们可以用到 fillna() 这个方法。

例如我们在刚才的数据中补充 0 :

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df.fillna(0))

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin       0.0         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       0.0         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

上面的示例是将所有的缺失数据全都填充成了 0 ,但是如果我们只想填充其中的一列数据呢?

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df.fillna({'read_num': 10}))

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin      10.0         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

为了便于区分,小编这里只补充了 read_num 这一列,将默认填充数值补充成了 10 。

重复数据处理

重复数据是指相同的记录有多条,这里一般简单的做删除操作。

Pandas 为我们提供了 drop_duplicates() 方法用作重复值处理,默认会对所有值进行判断,并且会默认保留第一个值。

为了演示,小编将 Excel 中的数据第一行复制了一条。

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df)

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
3        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
..        ...       ...       ...       ...       ...                 ...
404    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
405      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
407    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[409 rows x 6 columns]

print(df.drop_duplicates())

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
3        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
5      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
404    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
405      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
407    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

可以看到第一个示例中共有 409 行数据,到了第二个结果,就只剩 408 行数据了。

这个示例是针对整体值进行判断的,我们同样可以只针对某一列进行去重,只需要在 drop_duplicates() 这个方法中指明要判断的列即可:

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df.drop_duplicates(subset='read_num'))

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
3        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
5      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    cnblog     140.0         0      37.0         0 2020-02-20 23:00:08
404    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
405      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[342 rows x 6 columns]

可以看到这里只剩下了 342 行记录,当然对不对小编没有区验证,这个可以通过 sql 直接在数据库中做查询验证或者在 Excel 中使用去重进行验证(小编相信官方的 API 不会骗人)。

除了这些,还可以自定义删除重复项时保留哪个,默认是保留第一个,也可以设置保留最后一个,还可以设置一个都不保留:

import pandas as pd

# 相对路径
df = pd.read_excel("result_data.xlsx")

print(df.drop_duplicates(subset='plantform', keep='last'))

# 输出结果
    plantform  read_num  fans_num  rank_num  like_num         create_date
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
407    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

小编这里选择通过 plantform 字段进行去重筛选,从行号上看应该对的,保留了最后三条数据。

keep 的值默认是 first ,也就是只保留第一个,除了 first , last 还有一个是 False ,它的含义是一个都不保留。

本篇的内容就到这里结束了,希望各位同学能多动动手,多敲敲代码,虽然这是学代码最笨的办法,但同时也是最有效的方法。

示例代码

老规矩,所有的示例代码都会上传至代码管理仓库 Github 和 Gitee 上,方便大家取用。

示例代码-Github

示例代码-Gitee

posted @ 2020-02-26 09:47  极客挖掘机  阅读(639)  评论(0编辑  收藏  举报