使用Python进行大数据分析时开发者错误集锦(1)

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

时间:Wednesday, August 17, 2016  作者:John W. Baker and Pratik Weatherall


##1. 简介

Python是一门由于其能缩短开发时间而被广为人赞的开发语言,然而将Python有效得运用于大数据分析时却存在一些隐患。相同的能够使得工程开始阶段开发更简单的特性(例如动态性,宽松类型等)对于大型系统而言可能是衰落的开始;并且复杂的标准库,缓慢的运行时间以及设计之初未考虑数据整合等问题会快速的把节约的开发时间耗尽。

这篇文章将包含利用Python进行大数据分析时最常见的浪费时间的做法,并且会给出建议,让开发者能够回归正确的轨道,将时间花费在真正重要的地方:采用创造性的科学的方法从大规模多种类型的数据中获取有意义信息。


##2. 错误#1:重复造轮子

Python社区目前处在非常好的状态下,它所包含的数据分析的库拥有丰富的功能并且经过了严格的测试。所以,为什么要自己造轮子呢?

我在代码校验的过程中遇到了许多这样的问题。例如,开发者想要将一个CSV文件导入内存中来使用它。许多人会花费大量的时间编写自定义的CSV导入函数并且一贯地将它变成了一个索引又慢,转换又难的字典的字典。这导致他们没有足够的时间来真正挖掘数据。

进入这个泥塘——解决已经解决的问题——确实不该有什么理由。花几分钟时间Google一下或者问一下有经验的开发者一些数据分析库的建议就可以了。

顺便说一句,Python Pandas就是这样一个在这种情况下广泛使用的库。它为了处理大规模数据集而进行了有用的抽象,并且有许多功能可以进行ETLextract, transform, load),而且它拥有良好的性能。它允许简明的数据变换表达式以及提供了函数来导入,归一化和存储来自不同数据源或具有不同格式的数据,从而可以减少开发时间。

为了解释前者,假设我们有一个CSV文件,它的头包括ProductItersSold,我们想要找到10个最受欢迎的产品。让我们比较一下在vanilla Python中一个合理的实现和使用Python Pandas强大抽象能力的实现:

###2.1 Vanilla Python

blob.png

###2.2 Pandas

blob.png

注意到:利用vanilla Python来做这件事的确有一定的好处——它不需要将整个文件全部加载到内存里。然而,Pands实际上在背后做了很多优化I/O与性能的事情。另外,vanilla Python方法中内存里的销售字典也不够轻量级。

 

##3 错误#2:不去改善性能

当你的程序需要大量的时间来产生一个输出时,开发者的节奏与注意力就被破坏了。缓慢的程序也限制了一个开发者可以进行测试的次数——如果你的程序对一个小的数据集需要10分钟来获得输出结果的话,你可能一天只能调节执行你的代码大约30次。

所以,当你发现你无所事事坐着等代码执行的时候,也许是时候尝试着定位性能瓶颈。有一些专门的工具能够帮助开发者组织并加速代码。大多数这些工作都可在在IPython交互式Shell中完成。

IPython最简单的组织代码的方法是使用%timit魔法命令来获得一条Python语句的执行时间。你也可以下载一个更复杂的工具叫做line profiler。在运行IPython之后,键入:

blob.png

随后,你会获得一个像这样的表单,里面描述了在函数中哪一行执行了百分之多少的时间:

blob.png

对我个人而言,使用line profiler极大地帮助了我来定位使用上述的Python Pandas库的性能瓶颈,并通过修改代码实现了十倍的速度提升。

然而,如果你已经到了这样的地步,你确信问题的算法已经是复杂度及实现上都是最优的了,可能你需要为了性能Cython化一部分你的代码。使用上述的%timeit命令我们可以比较未Cython化和Cython化的版本的运行时间。

###3.1 未Cython化版本

将这个粘贴进IPython

blob.png

###3.2 Cython化的版本

如果你没有cythonmagic,安装它,并在IPython中键入:

blob.png

然后看一下结果:

blob.png

我们仅仅通过定义类型就实现了两个数量级的速度的提升。Cython魔法,名不虚传。


##4 错误#3:不理解time和timezones

开发者首次使用time模块时,Epoch time是一个很难掌握的奇怪的概念。需要理解的基本的概念是Epoch time在世界范围内对于任意一个给定的时刻数值都是一样的,但是如何将这个数字转换成一天的时刻是依赖于时区以及一年的时间(由于夏令时的存在)。当采用Python工作的时候,这些转换是由datetimepytz模块实现的。

Python的内建时间处理模块在函数的命名以及如何在不同的时间的表示上进行转换上非常复杂,十分类似它内部所基于的Ctime库。正确地使用它非常重要,因为时间序列中的数值是非常普通的。一个痛点是时区处理。一个通常的错误观念担心如下这个语句:

blob.png

当首次处理时区时,人们认为它会返回UTC格式的日期与时间。实际上,它返回的是命令所运行的机器的时区的日期与时间。这使得代码变得不可移植。我很辛苦才学到这一点,因为我将同一段代码部署在了本地机器以及在另一个国家的一台机器上,然后发现结果发生了怪异的偏离。

为了支持时区,pytz以及datetime模块是一种解决方案。它可以在UTC时间已知的情况下处理本地时间的创建,它也遵从夏令时规则。我们可以通过如下方法修改:

blob.png

然而,正如在官方文档中所描述的,有多种方法使用模块可能导致未知的结果因为pytzdatetime模块的互用性不够完善。在下面的例子里,我们期望在UTC与美国时区的冬天对于同一个日期与时间能够相差一小时,但是,结果并不是这样:

blob.png

本质上,Python原生的时间模块有时是简易的时间计数器有时却可能出现问题。当前的解决方案是可以工作的,但是开放的API是混乱的。在caliber库以及JavaJodaTime的采用之前都在Python中进行了实现,因而建议开发者要谨慎地使用,并要进行大量的测试以确保关于时间的方法确实做了他们应当做的事,此外还要检查这些方法返回的是UTC时间还是本地机器的时间,并且如果可能的话,尽量选择存储并使用UTC时间因为他们便于转换。

最新的在Python错综复杂的时间处理之上提供了一个更加简便的API的库包括Delorean, timesarrow.(未完待续)

 

英文原文:http://pythonprogramer.blogspot.com/2016/08/the-top-mistakes-developers-make-when.html
译者:LuCima
 

2月15日11:00到13:00网站停机维护,13:00前恢复
iPy智能助手 双击展开
查看更多聊天记录
(Ctrl+回车)换行