原始文章链接: https://towardsdatascience.com/how-to-make-your-pandas-loop-71-803-times-faster-805030df4f06

一、前言


如果你使用Python和Pandas进行数据分析,循环是不可避免要使用的。然而,即使对于较小的DataFrame来说,使用标准循环也是非常耗时的,对于较大的DataFrame来说,你懂的。今天,公众号为大家分享一个关于Pandas提速的小攻略,助你一臂之力!

二、 标准循环


Dataframe是Pandas对象,具有行和列。如果使用循环,你将遍历整个对象。Python不能利用任何内置函数,而且速度非常慢。 我们创建了一个包含65列和1140行的Dataframe。它包含了2016-2019赛季的足球比赛结果。我们希望创建一个新列,用于标注某个特定球队是否打了平局。

def soc_loop(leaguedf,TEAM,):
    leaguedf['Draws'] = 99999
    for row in range(0, len(leaguedf)):
        if ((leaguedf['HomeTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] == 'D')) | \
            ((leaguedf['AwayTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] == 'D')):
            leaguedf['Draws'].iloc[row] = 'Draw'
        elif ((leaguedf['HomeTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] != 'D')) | \
            ((leaguedf['AwayTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] != 'D')):
            leaguedf['Draws'].iloc[row] = 'No_Draw'
        else:
            leaguedf['Draws'].iloc[row] = 'No_Game'

正如你看到的,这个循环非常慢,花了20.7秒。让我们看看如何才能更有效率。

三、 iterrows():快321倍


在第一个例子中,我们循环遍历了整个DataFrame。Iterrows()为每一行返回一个 Series,因此它以索引对的形式遍历DataFrame,以Series的形式遍历目标列。这使得它比标准循环更快:

def soc_iter(TEAM,home,away,ftr):
    #team, row['HomeTeam'], row['AwayTeam'], row['FTR']
    if [((home == TEAM) & (ftr == 'D')) | ((away == TEAM) & (ftr == 'D'))]:
        result = 'Draw'
    elif [((home == TEAM) & (ftr != 'D')) | ((away == TEAM) & (ftr != 'D'))]:
        result = 'No_Draw'
    else:
        result = 'No_Game'
    return result

该代码运行时间为87毫秒,比标准循环快321倍。

但是,我们建议不要使用它,因为有更快的选择,而且iterrows()不能保留行之间的 dtype。这意味着,如果你在dataframe dtypes上使用iterrows() ,它会被更改,这可能会导致很多问题。如果一定要保留dtypes,也可以使用itertuple()。这里我们不详细讨论,你可以在这里找到官方文件:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.itertuples.html?source=post_page-----805030df4f06----------------------

四、 Apply():快811倍


apply本身并不快,但与DataFrame结合使用时,它具有很大的优势。这取决于apply表达式的内容。 如果它可以在Cython中执行,那么apply要快得多。

我们可以在Lambda函数中使用apply。 所要做的就是指定轴,使用axis=1,因为我们希望执行按列操作:

这段代码甚至比以前的方法更快,时间为27毫秒。

五、Pandas Vectorization:快9280倍


我们利用向量化的优势来创建真正高效的代码。关键是要避免案例1中那样的循环代码:

我们再次使用了开始时构建的函数。我们所要做的就是改变输入。我们直接将Pandas Series传递给我们的功能,这使我们获得了巨大的速度提升。

六、Numpy Vectorization:快71803倍


在前面的示例中,我们将Pandas Series传递给函数。通过adding.values,我们得到一个Numpy数组:

Numpy数组是如此之快,因为我们引用了局部性的好处:

访问局部性(locality of reference)

在计算机科学中,访问局部性,也称为局部性原理,是取决于存储器访问模式频繁访问相同值或相关存储位置的现象的术语。访问局部性有两种基本类型——时间和空间局部性。时间局部性是指在相对较小的持续时间内对特定数据和/或资源的重用。空间局部性是指在相对靠近的存储位置内使用数据元素。当数据元素被线性地排列和访问时,例如遍历一维数组中的元素,发生顺序局部性,即空间局部性的特殊情况。

局部性只是计算机系统中发生的一种可预测的行为。展示强访问局部性的系统是通过使用诸如在处理器核心的流水线级处的高速缓存,用于存储器的预取和高级分支预测器的技术的性能优化的良好候选者。

代码运行了0.305毫秒,比开始时使用的标准循环快了71803倍!

七、总结


我们比较了五种不同的方法,并根据一些计算将一个新列添加到我们的DataFrame中。我们注意到了速度方面的巨大差异:

请记住:

  1. 如果确定需要使用循环,则应始终选择apply方法。
  2. 否则,vectorization总是更好的,因为它更快!

文章参考

【转载】pandas中的循环的更多相关文章

  1. Oracle PL/SQL中的循环处理(sql for循环)

    今天来说下Oracle中的循环迭代处理,因为从自己的博客统计中看到,不少网友都搜索了关键字"SQL FOR循环",所以打算在这里说下个人的理解. PL/SQL也和我们常用的编程语言 ...

  2. Wpf中MediaElement循环播放

    原文:Wpf中MediaElement循环播放 前一段时间做了一个项目,里面牵涉到媒体文件的循环播放问题,在网上看了好多例子,都是在xaml中添加为MediaElement添加一个TimeLine,不 ...

  3. Spark与Pandas中DataFrame对比

      Pandas Spark 工作方式 单机single machine tool,没有并行机制parallelism不支持Hadoop,处理大量数据有瓶颈 分布式并行计算框架,内建并行机制paral ...

  4. [转载]java中的标号:outer的作用

    转载自:http://blog.sina.com.cn/s/blog_6f8bd746010136yr.html 标号label 标号提供了一种简单的break语句所不能实现的控制循环的方法,当在循环 ...

  5. Spark与Pandas中DataFrame对比(详细)

      Pandas Spark 工作方式 单机single machine tool,没有并行机制parallelism不支持Hadoop,处理大量数据有瓶颈 分布式并行计算框架,内建并行机制paral ...

  6. pandas中loc-iloc-ix的使用

    转自:https://www.jianshu.com/p/d6a9845a0a34 Pandas中loc,iloc,ix的使用 使用 iloc 从DataFrame中筛选数据 iloc 是基于“位置” ...

  7. Python学习教程:Pandas中第二好用的函数

    从网上看到一篇好的文章是关于如何学习python数据分析的迫不及待想要分享给大家,大家也可以点链接看原博客.希望对大家的学习有帮助. 本次的Python学习教程是关于Python数据分析实战基础相关内 ...

  8. Pandas中DateFrame修改列名

    Pandas中DateFrame修改列名 在做数据挖掘的时候,想改一个DataFrame的column名称,所以就查了一下,总结如下: 数据如下: >>>import pandas ...

  9. SQL中的循环、for循环、游标

    我们使用SQL语句处理数据时,可能会碰到一些需要循环遍历某个表并对其进行相应的操作(添加.修改.删除),这时我们就需要用到咱们在编程中常常用的for或foreach,但是在SQL中写循环往往显得那么吃 ...

随机推荐

  1. Vector使用方法简单整理

    使用vector,需要引用vector库: #include<vector> 首先,创建一个可以容纳int的vector变量——arr: vector<int> arr; 接着 ...

  2. hadoop2.7之作业提交详解(下)

    接着作业提交详解(上)继续写:在上一篇(hadoop2.7之作业提交详解(上))中已经讲到了YARNRunner.submitJob() [WordCount.main() -> Job.wai ...

  3. Selenium + python 测试环境搭建扩展-HTMLUNIT的使用

    尝试给公司的网站写每日例行检查的脚本时,不需要去打开浏览器,这是就用到HTMLUNIT的使用 HTMLUNIT是基于Selenium服务端的,所以需要selenium-server-standalon ...

  4. SoapUI使用教程---简介、下载、破解

    最近项目中要使用到SoapUI这款测试工具,之前有接触过,但好久没用了,借此机会记录并和大家分享一下. 一.soapui简介 soapui是一款开源测试工具,通过soap/http来检查.调用.实现W ...

  5. 微服务SpringCloud之Spring Cloud Config配置中心服务化

    在前面两篇Spring Cloud Config配置中心的博客中都是需要指定配置服务的地址url:spring.cloud.config.uri,客户端都是直接调用配置中心的server端来获取配置文 ...

  6. 三行脚本让 asp.net core 附加进程调试不再头痛

    在将项目升级到 asp.net core 2.2 后,很少使用 IIS Express 运行项目了,基本都是控制台运行或者写个脚本批量启动要运行的接口(多个输出项目),一直以为是我机器的 bug 关于 ...

  7. 《Effective Java第二版》总结

    第1条:考虑用静态工厂方法代替构造器 通常我们会使用 构造方法 来实例化一个对象,例如: // 对象定义 public class Student{ // 姓名 private String name ...

  8. MySql基础架构以及SQL语句执行流程

    01. mysql基础架构 SQL语句是如何执行的 学习一下mysql的基础架构,从一条sql语句是如何执行的来学习. 一般我们写一条查询语句类似下面这样: select user,password ...

  9. HDU 1079

    题意略. 思路:dfs记忆化搜索即可. #include<bits/stdc++.h> using namespace std; ][][]; ][]; bool is_leap(int ...

  10. Unity Shader 卡通渲染 基于退化四边形的实时描边

    从csdn转移过来,顺便把写过的文章改写一下转过来. 一.边缘检测算法 3D模型描边有两种方式,一种是基于图像,即在所有3D模型渲染完成一张图片后,对这张图片进行边缘检测,最后得出描边效果.一种是基于 ...