首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用Pandas&NumPy进行数据清洗的6大常用方法

数据科学家花了大量的时间清洗数据集,并将这些数据转换为他们可以处理的格式。事实上,很多数据科学家声称开始获取和清洗数据的工作量要占整个工作的80%。

因此,如果你正巧也在这个领域中,或者计划进入这个领域,那么处理这些杂乱不规则数据是非常重要的,这些杂乱数据包括一些缺失值,不连续格式,错误记录,或者是没有意义的异常值。

在这个教程中,我们将利用Python的和包来进行数据清洗。

主要内容如下:

删除 中的不必要 columns

改变 的 index

使用 方法来清洗 columns

使用 函数按元素清洗整个数据集

重命名 columns 为一组更易识别的标签

滤除 CSV文件中不必要的 rows

下面是要用到的数据集:

BL-Flickr-Images-Book.csv: 一份来自英国图书馆包含关于书籍信息的CSV文档

university_towns.txt: 一份包含美国各大洲大学城名称的text文档

olympics.csv: 一份总结了各国家参加夏季与冬季奥林匹克运动会情况的CSV文档

你可以从 的 GitHub repository 下载数据集来进行下面的例子。

注意:建议使用Jupter Notebooks来学习下面的知识。

学习之前假设你已经有了对Pandas和Numpy库的基本认识,包括Pandas的工作基础和对象,应用到这些对象上的常用方法,以及熟悉了NumPy的值。

让我们导入这些模块开始我们的学习。

删除DataFrame的列

经常的,你会发现数据集中不是所有的字段类型都是有用的。例如,你可能有一个关于学生信息的数据集,包含姓名,分数,标准,父母姓名,住址等具体信息,但是你只想分析学生的分数。

这个情况下,住址或者父母姓名信息对你来说就不是很重要。这些没有用的信息会占用不必要的空间,并会使运行时间减慢。

Pandas提供了一个非常便捷的方法函数来移除一个DataFrame中不想要的行或列。让我们看一个简单的例子如何从DataFrame中移除列。

首先,我们引入文件,并创建一个此文件的DataFrame。在下面这个例子中,我们设置了一个的相对路径,意味着所有的数据集都在文件夹下的当前工作目录中:

我们使用了方法得到了前五个行信息,这些列提供了对图书馆有帮助的辅助信息,但是并不能很好的描述这些书籍:, , , , , 。

因此,我们可以用下面的方法移除这些列:

在上面,我们定义了一个包含我们不要的列的名称列表。接着,我们在对象上调用函数,其中参数是,参数是。这告诉了Pandas,我们想要直接在我们的对象上发生改变,并且它应该可以寻找对象中被移除列的信息。

我们再次看一下DataFrame,我们会看到不想要的信息已经被移除了。

同样的,我们也可以通过给参数赋值直接移除列,而就不用分别定义to_drop列表和axis了。

这种语法更直观更可读。我们这里将要做什么就很明显了。

改变DataFrame的索引

Pandas索引扩展了Numpy数组的功能,以允许更多多样化的切分和标记。在很多情况下,使用唯一的值作为索引值识别数据字段是非常有帮助的。

例如,仍然使用上一节的数据集,可以想象当一个图书管理员寻找一个记录,他们也许会输入一个唯一标识来定位一本书。

让我们用把已经存在的索引改为这个列。

技术细节:不像在SQL中的主键一样,pandas的索引不保证唯一性,尽管许多索引和合并操作将会使运行时间变长如果是这样。

我们可以用一个直接的方法来获取每一条记录。尽管这个词可能看上去没有那么直观,但它允许我们使用基于标签的索引,这个索引是行的标签或者不考虑位置的记录。

换句话说,206是索引的第一个标签。如果想通过位置获取它,我们可以使用,是一个基于位置的索引。

之前,我们的索引是一个范围索引:从0开始的整数,类似Python的内建。通过给一个列名,我们就把索引变成了中的值。

你也许注意到了我们通过的返回变量重新给对象赋了值。这是因为,默认的情况下,这个方法返回一个被改变对象的拷贝,并且它不会直接对原对象做任何改变。我们可以通过设置参数来避免这个问题。

清洗数据字段

到现在为止,我们移除了不必要的列并改变了我们的索引,让它们变得更有意义。这个部分,我们将清洗特殊的列,并使它们变成统一的格式,这样可以更好的理解数据集和加强连续性。特别的,我们将清洗和。

根据上面观察,所有的数据类型都是dtype类型,差不多类似于Python中的str。

它包含了一些不能被适用于数值或是分类的数据。这也正常,因为我们正在处理这些初始值就是杂乱无章字符串的数据。

一个需要被改变为数值的的字段是所以我们做如下操作:

一本书只能有一个出版日期。因此,我们需要做以下的一些事情:

移除在方括号内的额外日期,任何存在的:1879[1878]。

将日期范围转化为它们的起始日期,任何存在的:1860-63;1839,38-54。

完全移除我们不关心的日期,并用Numpy的替换:[1879?]。

将字符串转化为Numpy的值。

考虑这些模式,我们可以用一个简单的正则表达式来提取出版日期:

上面正则表达式的意思在字符串开头寻找任何四位数字,符合我们的情况。

代表任何数字,重复这个规则四次。符号匹配一个字符串最开始的部分,圆括号表示一个分组,提示pandas我们想要提取正则表达式的部分。

让我们看看运行这个正则在数据集上之后会发生什么。

其实这个列仍然是一个类型,但是我们可以使用轻松的得到数字的版本:

这个结果中,10个值里大约有1个值缺失,这让我们付出了很小的代价来对剩余有效的值做计算。

结合str方法与Numpy清洗列

上面,你可以观察到的使用。这个属性是pandas里的一种提升字符串操作速度的方法,并有大量的Python字符串或编译的正则表达式上的小操作,例如,,和。

为了清洗字段,我们可以结合pandas的方法和numpy的函数配合完成。

它的语法如下:

这里,可以使一个类数组的对象,也可以是一个布尔表达。如果值为真,那么将被使用,否则使用。

它也可以嵌套使用,允许我们基于多个条件进行计算。

我们将使用这两个函数来清洗由于这列有字符串对象。以下是这个列的内容:

我们看到,对于一些行,还被一些其它没有用的信息围绕着。如果我们看更多的值,我们发现这种情况只适用于是"London"或者"Oxford"的行。

让我们看看两个特殊的:

这两本书在同一个地方出版,但是一个有连字符,另一个没有。

为了一次性清洗这个列,我们使用来获取一个布尔值。

我们清洗的列如下:

我们将它与结合。

这里,函数在一个嵌套的结构中被调用,是一个通过得到的布尔的。方法与Python内建的关键字一样,用于发现一个个体是否发生在一个迭代器中。

使用的替代物是一个代表我们期望的出版社地址字符串。我们也使用将连字符替换为空格,然后给DataFrame中的列重新赋值。

尽管数据集中还有更多的不干净数据,但是我们现在仅讨论这两列。

让我们看看前五行,现在看起来比我们刚开始的时候好点了。

在这一点上,就是一个很好的需要被转换成分类数据的类型,因为我们可以用整数将这相当小的唯一城市集编码。(分类数据的使用内存与分类的数量以及数据的长度成正比)

使用方法清洗整个数据集

在一定的情况下,你将看到并不是仅仅有一条列不干净,而是更多的。

在一些实例中,使用一个定制的函数到DataFrame的每一个元素将会是很有帮助的。的方法与内建的函数相似,并且简单的应用到一个中的所有元素上。

让我们看一个例子。我们将基于"university_towns.txt"文件创建一个。

我们可以看到每个state后边都有一些在那个state的大学城:。如果我们仔细观察state名字的写法,我们会发现它们都有"[edit]"的自字符串。

我们可以利用这个特征创建一个含有元组的列表,并将这个列表嵌入到中,

我们可以在DataFrame中包装这个列表,并设列名为"State"和"RegionName"。pandas将会使用列表中的每个元素,然后设置到左边的列,到右边的列。

最终的DataFrame是这样的:

我们可以像上面使用for loop来进行清洗,但是pandas提供了更简单的办法。我们只需要state name和town name,然后就可以移除所以其他的了。这里我们可以再次使用pandas的方法,同时我们也可以使用将一个python callable映射到DataFrame中的每个元素上。

我们一直在使用"元素"这个摄于,但是我们到底是什么意思呢?看看下面这个"toy"的DataFrame:

在这个例子中,每个单元 (‘Mock’, ‘Dataset’, ‘Python’, ‘Pandas’, etc.) 都是一个元素。因此,将分别应用一个函数到这些元素上。让我们定义这个函数。

pandas的只用一个参数,就是要应用到每个元素上的函数(callable)。

首先,我们定义一个函数,它将从DataFrame中获取每一个元素作为自己的参数。在这个函数中,检验元素中是否有一个或者。

基于上面的检查,函数返回相应的值。最后,函数被用在我们的对象上。现在DataFrame就看起来更干净了。

方法从DataFrame中提取每个元素,传递到函数中,然后覆盖原来的值。就是这么简单!

技术细节:虽然是一个方便和灵活的方法,但是对于大的数据集它将会花费很长时间运行,因为它需要将python callable应用到每个元素上。一些情况中,使用Cython或者NumPY的矢量化的操作会更高效。

重命名列和移除行

经常的,你处理的数据集会有让你不太容易理解的列名,或者在头几行或最后几行有一些不重要的信息,例如术语定义,或是附注。

这种情况下,我们想重新命名列和移除一定的行以让我们只留下正确和有意义的信息。

为了证明我们如何处理它,我们先看一下"olympics.csv"数据集的头5行:

现在我们将它读入pandas的DataFrame。

这的确有点乱!列名是以整数的字符串形式索引的,以0开始。本应该是列名的行却处在。发生这个是因为CSV文件以0, 1, 2, …, 15起始的。

同样,如果我们去数据集的源文件观察,上面的真的应该是像"Country"这样的,应该代表"Summer Games", 而应该是"Gold"之类的。

因此,我们需要做两件事:

移除第一行并设置header为第一行

重新命名列

当我们读CSV文件的时候,可以通过传递一些参数到函数来移除行和设置列名称。

这个函数有很多可选参数,但是这里我们只需要来移除第0行:

我们现在有了设置为header的正确行,并且所有没用的行都被移除了。记录一下pandas是如何将包含国家的列名改变为的。

为了重命名列,我们将使用DataFrame的方法,允许你以一个映射(这里是一个字典)重新标记一个轴。

让我们开始定义一个字典将现有的列名称(键)映射到更多的可用列名称上(字典的值)。

我们在对象上调用函数:

设置为可以让我们的改变直接反映在对象上。让我们看看是否正确:

Python数据清洗:回顾

这个教程中,你学会了从数据集中如何使用函数去除不必要的信息,也学会了如何为数据集设置索引,以让items可以被容易的找到。

更多的,你学会了如何使用清洗对象字段,以及如何使用对整个数据集清洗。最后,我们探索了如何移除CSV文件的行,并且使用方法重命名列。

掌握数据清洗非常重要,因为它是数据科学的一个大的部分。你现在应该有了一个如何使用pandas和numpy进行数据清洗的基本理解了。更多内容可参考pandas和numpy官网。

参考:https://realpython.com/python-data-cleaning-numpy-pandas/

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180401G0NFOA00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券