懒人秘籍:教你如何避免编写pandas代码
读芯术   读芯术   2020-01-03

Pandas在数量科学领域无需介绍,他提供高性能,轻而易举使用的多寡结构和数据分析工具。但是,在拍卖过多之多寡时,单核上之Pandas就显得力不从心了,大家不得不求助于不同之分布式系统来提高性能。然而,增长性能的衡量常常伴随着陡峭的学习曲线。

而大家都在尽可能地避免这种悬崖峭壁,结果可想而知,都转向了如何避免编写pandas代码。

在过去4年里,作者一直采取pandas表现数据分析的首要工具。必须承认,“如何避免编写pandas代码”的多数内容来自于使用pandas编程的启动阶段。在开展代码审阅时,作者仍然看到许多经验丰富的程序员在看有的热门“如何避免使用”的帖子。

在本文中,作者首先展示了一番“如何避免”的例证,下一场展示了一番正确的“如何使用”pandas来计算统计数据的主意。改善后,代码更简洁、易读,推行更快。告知时间之公式为: 831 ms ± 25.7 ms per loop,即平均831毫秒,标准偏差为25.7毫秒。每个代码示例执行多次,以计算准确的推行时间。

和过去一样,可以下载 JupyterNotebook并在计算机上试用。

起来pandas游戏之旅,请阅读如下资源:

  • 5个鲜为人知的pandas技术
  • 采用pandas拓展批判性数据分析
  • 来源:Pexels

    安装

         
    1. from platform importpython_versionimport numpy as np 
    2. import pandas as pdnp.random.seed(42) # set the seed tomake examples repeatable 

    样本数据集

    样本数据集包含各个城市之订货信息,是随机的,唯一目的是展示样本。

    数量集有三趟:

  • id表示唯一的标识
  • city表示预定的都市信息
  • booked perc表示一定时间预定的比重
  • 数量集有一万枝,这使速度改进更加强烈。瞩目,如果代码以科学的pandas办法编写,pandas可以采取DataFrames计算数百万(甚至数十亿)列的统计数据。

         
    1. size = 10000cities =["paris", "barcelona", "berlin", "newyork"]df = pd.DataFrame( 
    2.     {"city": np.random.choice(cities,sizesize=size), "booked_perc": np.random.rand(size)} 
    3. df["id"] = df.index.map(str) +"-" + df.city 
    4. dfdf = df[["id", "city", "booked_perc"]] 
    5. df.head() 

    1. 如何避免对数据求和

    翻滚的熊猫/Reddit

    来自Java世界之荣誉感,把“多列for循环”使用到了Python。

    计算booked perc趟的总额,把百分比加起来毫无意义,但无论如何,一起来试试吧,实行出真知。

         
    1. %%timeitsuma = 0 
    2. for _, row in df.iterrows(): 
    3.     suma += row.booked_perc766ms ± 20.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

    更符合Python作风的措施来对进求和如下:

         
    1. %%timeitsum(booked_perc forbooked_perc in df.booked_perc)989 µs ± 18.5 µs per loop (mean ±std. dev. of 7 runs, 1000 loops each)%%timeitdf.booked_perc.sum()92µs ± 2.21 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 

    正如预期的那样,先后一个示例是最慢的——对一万项求和几乎需要1秒。其次个比喻的进度的快令人惊奇。

    是的的主意是采取pandas对数据进行求和(或对进使用任何其他操作),这是第三个示例——也是最快的!

    2. 如何避免过滤数据

    玩耍的熊猫/Giphy

    尽管在采取pandas先前,作者已经很熟悉numpy,并利用for循环来过滤数据。求和时,还是可以观察到性能上的差别。

         
    1. %%timeitsuma = 0 
    2. for _, row in df.iterrows(): 
    3.     if row.booked_perc <=0.5: 
    4.         suma += row.booked_perc831ms ± 25.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)%%timeitdf[df.booked_perc<= 0.5].booked_perc.sum()724 µs ± 18.8 µs per loop(mean ± std. dev. of 7 runs, 1000 loops each) 

    正如预期的一样,其次个比喻比第一个例子快很多

    如果加入更多的变压器呢?只需把它们添加到括号里:

         
    1. %%timeitdf[(df.booked_perc <=0.5) & (df.city == 'new york')].booked_perc.sum()1.55ms ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 

    3. 如何避免访问以前的值

    翻滚的熊猫/Giphy

    你可能会说:好吧,但是如果需要访问先前某一趟的值呢,还是要求一个for循环。你错了!

    离别使用和不采取for循环来计算一行到另一行百分数的变动

         
    1. %%timeitfor i inrange(1, len(df)): 
    2.     df.loc[i,"perc_change"] =  (df.loc[i].booked_perc- df.loc[i - 1].booked_perc) / df.loc[i- 1].booked_perc7.02 s ± 24.4 ms per loop (mean ± std. dev. of 7runs, 1 loop each)%%timeitdf["perc_change"] = df.booked_perc.pct_change()586µs ± 17.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 

    同样,其次个比喻比第一个用到for循环的例证快得多。

    pandas有成千上万函数可以根据以前的值计算统计数据(例如shift函数对值进行运动)。该署函数接受periods数,可以在计算中包含以前值的多寡。

    4. 如何避免使用复杂的函数

    来源:坠落的熊猫(江山化工)Giphy

    有时需要在DataFrame官方采用复杂函数(有多个变量的函数)。让咱将下南宁的booking_perc两两相乘,其它设置为0并且把这趟命名为sales_factor。

    作者首先想到的是采取iterrows的for循环。

         
    1. %%timeitfor i, row in df.iterrows(): 
    2.     if row.city =='new york': 
    3.         df.loc[i, 'sales_factor'] =row.booked_perc * 2 
    4.     else: 
    5.         df.loc[i, 'sales_factor'] =03.58 s ± 48.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

    一度更好的措施是直接在DataFrame上采取函数。

         
    1. %%timeitdef calculate_sales_factor(row): 
    2.     if row.city =='new york': 
    3.         return row.booked_perc* 2 
    4.     return 0df['sales_factor'] =df.apply(calculate_sales_factor, axis=1)165 ms ± 2.48 ms per loop(mean ± std. dev. of 7 runs, 10 loops each) 

    最快的主意是采取pandas玉器直接计算函数值。

         
    1. %%timeit df.loc[df.city== 'new york', 'sales_factor'] = df[df.city == 'newyork'].booked_perc * 2 
    2. df.sales_factor.fillna(0, inplace=True)3.03 ms ± 85.5 µsper loop (mean ± std. dev. of 7 runs, 100 loops each) 

    可以看出从第一个例子到最后一个之加快过程。

    顶解决有3个及3个以上变量的函数时,可以把他分解为多个pandas分立式。这比运用函数更快。

         
    1. Eg: f(x, a, b) = (a + b) * x 
    2. df['a_plus_b'] = df['a'] +df['b'] 
    3. df['f'] = df['a_plus_b'] * df['x'] 

    5. 如何避免对数据进行分组

    蹭痒熊猫/Giphy

    如今得以看出,在初始采取pandas先前,作者更多依赖于for循环。至于对数据进行分组,如果充分发表pandas的劣势,可以减少代码行数。

    要计算如下数据:

  • 一度城市之平均sales factor
  • 一度城市之第一预定id
  •      
    1. %%timeit avg_by_city = {} 
    2. count_by_city = {} 
    3. first_booking_by_city = {}for i, row in df.iterrows(): 
    4.     city = row.city 
    5.     if city in avg_by_city: 
    6.         avg_by_city[city] += row.sales_factor 
    7.         count_by_city[city] += 1 
    8.     else: 
    9.         avg_by_city[city] = row.sales_factor 
    10.         count_by_city[city] = 1 
    11.         first_booking_by_city[city] =row['id']for city, _ in avg_by_city.items(): 
    12.     avg_by_city[city] /=count_by_city[city]878 ms ± 21.4 ms per loop (mean ± std. dev. of 7 runs, 1 loopeach) 

    Pandas有分组操作所以不必在DataFrame上开展迭代,pandas的分组操作和SQL的GROUP BY说话一样的。

         
    1. %%timeitdf.groupby('city').sales_factor.mean() 
    2. df.groupby('city').sales_factor.count() 
    3. df.groupby('city').id.first()3.05 ms ± 65.3 µs per loop(mean ± std. dev. of 7 runs, 100 loops each)%%timeitdf.groupby("city").agg({"sales_factor":["mean", "count"], "id": "first"})4.5ms ± 131 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

    惊奇的是,先后三个比喻不是最快的,但比第二个比喻更简洁。作者建议,如果需要加速的编码,请用第二种办法。

    愉悦的熊猫/Giphy

    说到底,小芯的提议是:如果需要采取pandas编纂for循环,那一定存在一种更好的编制方式。

    会生活一些计算量很大的函数,即使上述的僵化方法也会劳而无功。这就是说我们就要求采取最后手段:Cython和Numba。

    大家一起来试试这些办法吧,一定会有意想不到的收获~

    【编纂推荐】

    1. 一张图帮你记忆,Spring Boot使用在起步阶段实施代码的几种方法
    2. 一行代码简化Python独特信息:错误清晰指出,排版简洁美观
    3. 必发娱乐手机版的编码都写完了吗?不如做个Python速度条看看还剩多少
    4. Mozilla 通告 MDN Web 付出人员要求评估报告
    5. 好用哭了!8大开发员必备之网页应用程序
    【义务编辑: 赵宁宁 TEL:(010)68476606】

     

    分享到朋友圈 分享到微博
  • pandas
  • 代码
  • 付出
  • 相关推荐

    React vs Angular vs Vue.js - 到底怎么选择?

    2020-01-09 15:35:54

    Kubernetes vs Docker:刺探容器和编排

    2020-01-09 15:28:30

    腾讯大佬告诉你,写Python到底用什么IDE正好

    2020-01-09 13:24:31

    Copyright © 2005-2020 51CTO.COM 必发娱乐登入
    情节话题
    必发娱乐登入 移步 传感器 系统 安全 网络 必发娱乐登录 虚拟化 付出
    热门产品
    51CTO必发娱乐登录 51CTO高招 移步开发者服务联盟网+ 51CTO博客 WOT碰头会



          &lt;code id="7be896f8"&gt;&lt;/code&gt;


          &lt;blockquote id="8fd87c4e"&gt;&lt;/blockquote&gt;