查看原文
其他

软件应用 | 手把手教你用pandas处理缺失值

数据Seminar 2022-12-31

The following article is from 大数据DT Author Wes McKinney


本文转载自公众号大数据DT(ID:hzdashuju)

本文摘编自《利用Python进行数据分析》(原书第2版),经出版方授权发布

作者:韦斯·麦金尼(Wes McKinney)

译者:徐敬一




导读


在进行数据分析和建模的过程中,大量的时间花在数据准备上:加载、清理、转换和重新排列。本文将讨论用于缺失值处理的工具。

缺失数据会在很多数据分析应用中出现。pandas的目标之一就是尽可能无痛地处理缺失值。


pandas对象的所有描述性统计信息默认情况下是排除缺失值的。
pandas对象中表现缺失值的方式并不完美,但是它对大部分用户来说是有用的。对于数值型数据,pandas使用浮点值NaN(Not a Number来表示缺失值)。我们称NaN为容易检测到的标识值:
In : 
string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])string_data

Out:
0 aardvark1 artichoke2 NaN3 avocadodtype: object
In:
string_data.isnull()

Out:
0 False1 False2 True3 Falsedtype: bool
在pandas中,我们采用了R语言中的编程惯例,将缺失值成为NA,意思是not available(不可用)。在统计学应用中,NA数据可以是不存在的数据或者是存在但不可观察的数据(例如在数据收集过程中出现了问题)。当清洗数据用于分析时,对缺失数据本身进行分析以确定数据收集问题或数据丢失导致的数据偏差通常很重要。

Python内建的None值在对象数组中也被当作NA处理:

In:
string_data[0] = Nonestring_data.isnull()

Out:
0 True1 False2 True3 Falsedtype: bool
pandas项目持续改善处理缺失值的内部细节,但是用户API函数,比如pandas. isnull,抽象掉了很多令人厌烦的细节。处理缺失值的相关函数列表如下:
  • dropna:根据每个标签的值是否是缺失数据来筛选轴标签,并根据允许丢失的数据量来确定阈值
  • fillna:用某些值填充缺失的数据或使用插值方法(如“ffill”或“bfill”)。
  • isnull:返回表明哪些值是缺失值的布尔值
  • notnull:isnull的反作用函数

01 过滤缺失值
有多种过滤缺失值的方法。虽然你可以使用pandas.isnull和布尔值索引手动地过滤缺失值,但dropna在过滤缺失值时是非常有用的。在Series上使用dropna,它会返回Series中所有的非空数据及其索引值:
In:
from numpy import nan as NAdata = pd.Series([1, NA, 3.5, NA, 7])data.dropna()

Out:
0 1.02 3.54 7.0dtype: float64
上面的例子与下面的代码是等价的:
In:
data[data.notnull()]

Out:
0 1.02 3.54 7.0dtype: float64
当处理DataFrame对象时,事情会稍微更复杂一点。你可能想要删除全部为NA或包含有NA的行或列。dropna默认情况下会删除包含缺失值的行:
In:
data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA] [NA, NA, NA], [NA, 6.5, 3.]])cleaned = data.dropna()data

Out:
0 1 20 1.0 6.5 3.01 1.0 NaN NaN2 NaN NaN NaN3 NaN 6.5 3.0
In:
cleaned

Out:
0 1 20 1.0 6.5 3.0
传入how='all’时,将删除所有值均为NA的行:
In:
data.dropna(how='all')

Out:
0 1 20 1.0 6.5 3.01 1.0 NaN NaN3 NaN 6.5 3.0
如果要用同样的方式去删除列,传入参数axis=1:
In:
data[4] = NAdata

Out:
0 1 2 40 1.0 6.5 3.0 NaN1 1.0 NaN NaN NaN2 NaN NaN NaN NaN3 NaN 6.5 3.0 NaN
In:
data.dropna(axis=1, how='all')
Out:
0 1 20 1.0 6.5 3.01 1.0 NaN NaN2 NaN NaN NaN3 NaN 6.5 3.0
过滤DataFrame的行的相关方法往往涉及时间序列数据。假设你只想保留包含一定数量的观察值的行。你可以用thresh参数来表示:
In:
df = pd.DataFrame(np.random.randn(7, 3))df.iloc[:4, 1] = NAdf.iloc[:2, 2] = NAdf

Out:
0 1 20 -0.204708 NaN NaN1 -0.555730 NaN NaN2 0.092908 NaN 0.7690233 1.246435 NaN -1.2962214 0.274992 0.228913 1.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741
In:
df.dropna()
Out:
0 1 24 0.274992 0.228913 1.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741
In:
df.dropna(thresh=2)
Out:
0 1 22 0.092908 NaN 0.7690233 1.246435 NaN -1.2962214 0.274992 0.228913 1.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741
02 补全缺失值
你有时可能需要以多种方式补全“漏洞”,而不是过滤缺失值(也可能丢弃其他数据)。
大多数情况下,主要使用fillna方法来补全缺失值。调用fillna时,可以使用一个常数来替代缺失值:
In:
df.fillna(0)
Out:
0 1 20 -0.204708 0.000000 0.0000001 -0.555730 0.000000 0.0000002 0.092908 0.000000 0.7690233 1.246435 0.000000 -1.2962214 0.274992 0.228913 1.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741
在调用fillna时使用字典,你可以为不同列设定不同的填充值:
In:
df.fillna({1: 0.5, 2: 0})

Out:
0 1 20 -0.204708 0.500000 0.0000001 -0.555730 0.500000 0.0000002 0.092908 0.500000 0.7690233 1.246435 0.500000 -1.2962214 0.274992 0.228913 1.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741
fillna返回的是一个新的对象,但你也可以修改已经存在的对象:
In:
_ = df.fillna(0, inplace=True)df

Out:
0 1 20 -0.204708 0.000000 0.0000001 -0.555730 0.000000 0.0000002 0.092908 0.000000 0.7690233 1.246435 0.000000 -1.2962214 0.274992 0.228913 1.3529175 0.886429 -2.001637 -0.3718436 1.669025 -0.438570 -0.539741
用于重建索引的相同的插值方法也可以用于fillna:
In:
df = pd.DataFrame(np.random.randn(6, 3))df.iloc[2:, 1] = NAdf.iloc[4:, 2] = NAdf

Out:
0 1 20 0.476985 3.248944 -1.0212281 -0.577087 0.124121 0.3026142 0.523772 NaN 1.3438103 -0.713544 NaN -2.3702324 -1.860761 NaN NaN5 -1.265934 NaN NaN
In:
df.fillna(method='ffill')
Out:
0 1 20 0.476985 3.248944 -1.0212281 -0.577087 0.124121 0.3026142 0.523772 0.124121 1.3438103 -0.713544 0.124121 -2.3702324 -1.860761 0.124121 -2.3702325 -1.265934 0.124121 -2.370232
In:
df.fillna(method='ffill', limit=2)
Out:
0 1 20 0.476985 3.248944 -1.0212281 -0.577087 0.124121 0.3026142 0.523772 0.124121 1.3438103 -0.713544 0.124121 -2.3702324 -1.860761 NaN -2.3702325 -1.265934 NaN -2.370232
使用fillna你可以完成很多带有一点创造性的工作。例如,你可以将Series的平均值或中位数用于填充缺失值:
In:
data = pd.Series([1., NA, 3.5, NA, 7])data.fillna(data.mean())

Out:
0 1.0000001 3.8333332 3.5000003 3.8333334 7.000000dtype: float64
以下是fillna的函数参数。
  • value:标量值或字典型对象用于填充缺失值
  • method:插值方法,如果没有其他参数,默认是'ffill'
  • axis:需要填充的轴,默认axis=0
  • inplace:修改被调用的对象,而不是生成一个备份
  • limit:用于前向或后向填充时最大的填充范围


关于作者


韦斯·麦金尼(Wes McKinney)

是流行的Python开源数据分析库pandas的创始人。他是一名活跃的演讲者,也是Python数据社区和Apache软件基金会的Python/C++开源开发者。目前他在纽约从事软件架构师工作。




·END·


星标⭐我们不迷路!

想要文章及时到,文末“在看”少不了!


点击搜索你感兴趣的内容吧


往期推荐


统计计量 | 经管十大好书推荐!

学术前沿 | 《Science of The Total Environment》:气候变化对中国牧区畜牧业生产的影响

招聘资讯 | 出发2021!CCAD面向全国农经类专业人才招募计划

推荐 | C刊(各学科)2021年重点选题方向汇总!

招聘资讯 | 出发2021!CCAD面向全国农经类专业人才招募计划

学术前沿 | C刊三农及相关领域2021年重点选题方向汇总!

报告分享 | 全球智慧农业领域学科态势分析报告(1995-2018年)







数据Seminar




这里是大数据、分析技术与学术研究的三叉路口



推荐 | 青酱



    欢迎扫描👇二维码添加关注    

点击下方“阅读全文”了解更多

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存