专栏首页量化投资与机器学习1000+倍!超强Python『向量化』数据处理提速攻略

1000+倍!超强Python『向量化』数据处理提速攻略

作者:Cheever

编译:1+1=6

今天公众号给大家好好讲讲基于Pandas和NumPy,如何高速进行数据处理!

1

向量化

1000倍的速度听起来很夸张。Python并不以速度著称。这是真的吗?当然有可能 ,关键在于你如何操作!

如果在数据上使用for循环,则完成所需的时间将与数据的大小成比例。但是还有另一种方法可以在很短的时间内得到相同的结果,那就是向量化。

这意味着要花费15秒的时间来编写代码,并且在15毫秒的时间内跑出结果。

当然,根据数据集的不同,库文件、硬件版本的不同,所以实际结果可能会有所不同。

那么什么是向量化?

简而言之,向量化是一种同时操作整个数组而不是一次操作一个元素的方法,这也得益于Numpy数组。

我们先导入测试数据:

第一次向量化测试:

以这个函数为例。这是一个非常基本的条件逻辑,我们需要为lead status创建一个新列。

我们使用Pandas的优化循环函数apply(),但它对我们来说太慢了。

或者使用如下方法:

接下来,我们尝试一下使用向量化。将整个Series作为参数传递到函数中,而不是对每一行。

但没有成功。if语句试图确定Series作为一个整体的真实性,而不是比较Series中的每个元素,所以这是错误的

2

numpy.where()

语法很简单,就像Excel的IF()。

第一个参数是逻辑条件Numpy,它将为数组中的每个元素计算一个布尔数组。当条件满足且为True时,将返回第二个参数,否则返回第三个参数。

看下面的例子:

numpy.where()它从我们的条件中创建一个布尔数组,并在条件为真或假时返回两个参数,它对每个元素都这样做。这对于在Dataframe中创建新列非常有用。

比apply函数快344倍!

如果我们在Series添加了.values ,它的作用是返回一个NumPy数组,里面是我的级数中的数据。

现在的numpy.where(),只查看数组中的原始数据,而不必负责Pandas Series带来的内容,如index或其他属性。这个小的变化通常会在时间上产生巨大的差异。

各位!一开始,我们应用的if/else函数的时间超过了8秒,现在我们已经将其缩短到不到9毫秒,这几乎是一个1000倍的转换!

3

numpy.vectorize()

这个函数将把Python函数转换成NumPy ufunc,这样它就可以处理向量化的方法。它向量化了你的函数,而不一定是这个函数如何应用于你的数据,这有很大的不同!

例子如下:

vectorize()将常规的Python函数转换成Numpy ufunc(通用函数),这样它就可以接收Numpy数组并生成Numpy数组。vectorize()主要是为了方便,而不是为了性能。实质上是一个for loop。

我们可以使用它的一种方式,包装我们之前的函数,在我们传递列时不起作用的函数,并向量化它。它比.apply()快得多,但也比.where()慢了17倍。所以在这种情况下,将坚持使用np.where()!

一些人认为这更快:使用index设置,但事实证明它实际上不是向量化!

代码如下:

4

Multiple conditions

类似这样的多个if/elif/elifs,如何向量化呢?

你可以调用np.where在任何情况下,代码长了就变得有点难读了

实际上有一个函数专门可以做多重条件的向量化,是什么呢?

5

numpy.select()

向量化if...elif...else。更简洁(甚至更快)和做多重嵌套np.where。

np.select()的一个优点是它的layout。

你可以用你想要检查的顺序来表达你想要检查的条件。np.select将按从前到后的顺序对每个数组求值,当数据集中的某个给定元素的第一个数组为True时,将返回相应的选择。所以操作的顺序很重要!像np.where。其中,你的选择可以是标量,也可以是数组。只要它符合你的条件。

这是我们第一次尝试将多个条件从.apply()方法转换为向量化的解决方案。向量化选项将在0.1秒多一点的时间内返回列,.apply()将花费12.5秒。嵌套的np.where()解决方案工具179ms。

那么嵌套的多个条件,我们可以向量化吗?可以!

代码:

基本上,当使用np.select()时。根据经验,你需要为每个return语句设置n个条件,这样就可以将所有布尔数组打包到一个条件中,以返回一个选项。

代码如下:

如果添加了.values:

4

更复杂的

有时必须使用字符串,有条件地从字典中查找内容,比较日期,有时甚至需要比较其他行的值。我们来看看!

1、字符串

假设你需要在一系列文本中搜索特定的模式,如果匹配,则创建一个新的series。这是一种.apply方法。

用np.vectorize()时:

同时,当使用向量化方法处理字符串时,Pandas为我们提供了向量化字符串操作的.str()。contains基本上和re.search做的是一样的,它会给我们相同的结果。

为什么.str向量化这么慢?

字符串操作很难并行化,所以.str方法是向量化的,这样就不必为它们编写for循环。使用.apply执行基本的Python是更快的选择。

一般来说,我们还建议你使用str方法来避免循环,但是如果你的速度变慢了,这会让你很痛苦,试试循环是否能帮你节省一些时间。

2、字典lookups

对于进行字典查找,我们可能会遇到这样的情况,如果为真,我们希望从字典中获取该series键的值并返回它,就像下面代码中的下划线一样。

你可以使用.map()在向量化方法中执行相同的操作。

3、日期

有时你可能需要做一些日期计算(确保你的列已经转换为datetime对象)。这是一个计算周数的函数。以天为单位的两个日期之差除以7得到过去的周数。下面是使用.apply()的方法。

有两种向量化方法。第一种方法是使用pandas .dt series datetime访问器。除了改变语法以适应np.where。我们要做的就是在.dt之前加上.days ,效果很好。

完成此计算的另一种更加Numpy向量化的方法是将Numpy数组转换为timedeltas,获得day值,然后除以7。这和最终结果是一样的,只是下面的那个代码更长。

4、使用来自其他行的值

在这个例子中,我们从Excel中重新创建了一个公式:

其中A列表示id,L列表示日期。

向量化所需要的所有函数都是在同一行上比较的值,这可以使用pandas.shift()实现!

确保你的数据正确排序,否则你的结果就没有意义!

很慢!

为了解决这个问题,我们对Pandas中的一个series使用.shift()将前一行移到相同的级别。一旦它们被转移到相同的级别,我就可以使用np.select()执行相同的条件向量化方法了!

5

其他

一种选择是使用apply跨CPU核并行化操作。因此,如果你有一个4核的i7,你可以将你的数据集分成4块,将你的函数应用到每一块,然后将结果合并在一起。注意:这不是一个很好的选择!

Dask是在Pandas API中工作的一个不错的选择。能够跨集群扩展到TB级的数据,或者甚至能够更有效地在一台机器上处理多核数据。

6

总结

向量化可以极大地加快速度!

  • np.where →一个逻辑条件
  • np.select →2+逻辑条件

如果你正在处理字符串/正则表达式函数,那么最好还是使用Python。或者如果你的逻辑重写起来很麻烦或者你不想重写,你可以考虑并行化应用函数或者像Dask这样的东西可以帮你实现。

最后,在优化之前一定要确保逻辑是合理的。

不成熟的优化是万恶之源!

本文分享自微信公众号 - 量化投资与机器学习(Lhtz_Jqxx),作者:QIML编辑部

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 高频交易:数学重要?还是技术重要?

    各位读者,如果让你回答这个问题:高频交易:数学重要?还是技术重要?你觉得哪个重要呢?在这里。我们给大家普及一些涉及高频交易的专业术语:

    量化投资与机器学习微信公众号
  • 【划重点!】上周机器学习与量化投资论坛精华锦集

    量化投资与机器学习微信公众号
  • 机器学习在统计套利中的应用

    谢谢大家的支持!现在该公众号开通了评论留言功能,你们对每篇推文的留言与问题,可以通过【写评论】给圈主留言,圈主会及时回复您的留言。 1. 简介 在投资领域,统计...

    量化投资与机器学习微信公众号
  • 【AI白身境】学AI必备的python基础

    人生苦短,必须学好python!python现在火的程度已经不需要我多言了,它为什么为火,我认为有两个原因,第一是人工智能这个大背景,第二是它真的太容易学了,没...

    用户1508658
  • 转:自旋锁(spinlock)

    自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就...

    流柯
  • 复习python第四天

    昨天刷了一遍python二级题库的模拟题,怎么说呢一些数据库的和数据结构的之前只是草草来了解,所以都不会做,但是那些python相关的题目都是相当的基础吖,没什...

    sjw1998
  • vivo 大规模特征存储实践

    本文旨在介绍 vivo 内部的特征存储实践、演进以及未来展望,抛砖引玉,吸引更多优秀的想法。

    2020labs小助手
  • 多线程编程之自旋锁

      自旋锁是专为防止多处理器并发(实现保护共享资源)而引入的一种锁机制。自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,...

    物流IT圈
  • 关于js拿shell的尝试

    以前在测试一个网站的时候,大佬提供了一个拿shell的思路,通过js拿到了shell。

    天钧
  • Tungsten Fabric入门宝典丨开始第二天的工作

    首次启动和运行,以及运营安装之后。用户需要查看运行状态(例如路由表和vif状态),并在Tungsten Fabric DB中配置各种对象,例如virtual-n...

    Tungsten Fabric

扫码关注云+社区

领取腾讯云代金券