亚洲国产成人精品久久_欧美日韩国产综合一区二区_亚洲精品理论电影_色综合久久中文字幕

懶人秘籍_教你如何避免編寫pandas代碼

放大字體  縮小字體 發布日期:2020-01-02  來源:來自互聯網  作者:來自互聯網  瀏覽次數:850
導讀

在本文中,筆者首先展示了一個“如何避免”的例子,然后展示了一個正確的“如何使用”pandas來計算統計數據的方法。 正確的方法是使用pandas對數據進行求和(或對列使用任何其他操作),這是第三個示…

全文共4781字,預計學習時長14分鐘

全文共4781字,預計學習時長14分鐘

來源:Pexels

Pandas在數據科學領域無需介紹,它提供高性能,易于使用的數據結構和數據分析工具。但是,在處理過多的數據時,單核上的Pandas就顯得心有余而力不足了,大家不得不求助于不同的分布式系統來提高性能。然而,提高性能的權衡常常伴隨著陡峭的學習曲線。

而大家都在盡可能地避免這種懸崖峭壁,結果可想而知,都轉向了如何避免編寫pandas代碼。

在過去4年里,筆者一直使用pandas作為數據分析的主要工具。必須承認,“如何避免編寫pandas代碼”的大部分內容來自于使用pandas編程的起步階段。在進行代碼審閱時,筆者仍然看到許多經驗豐富的程序員在看一些熱門“如何避免使用”的帖子。

在本文中,筆者首先展示了一個“如何避免”的例子,然后展示了一個正確的“如何使用”pandas來計算統計數據的方法。改進后,代碼更簡潔、易讀,執行更快。報告時間的格式為: 831 ms ± 25.7 ms per loop,即平均831毫秒,標準偏差為25.7毫秒。每個代碼示例執行多次,以計算準確的執行時間。

和往常一樣,可以下載 JupyterNotebook并在電腦上試運行。

開始pandas游戲之旅,請閱讀如下資源:

  • 5個鮮為人知的pandas技巧
  • 使用pandas進行探索性數據分析

來源:Pexels

設置

  • from platform importpython_versionimport numpy as npimport pandas as pdnp.random.seed(42) # set the seed tomake examples repeatable

樣本數據集

樣本數據集包含各個城市的預訂信息,是隨機的,唯一目的是展示樣本。

數據集有三列:

  • id表示唯一的標識
  • city表示預定的城市信息
  • booked perc表示特定時間預定的百分比

數據集有一萬條,這使速度改進更加明顯。注意,如果代碼以正確的pandas方式編寫,pandas可以利用Dataframes計算數百萬(甚至數十億)行的統計數據。

  • size = 10000cities =["paris", "barcelona", "berlin", "newyork"]df = pd.Dataframe( {"city": np.random.choice(cities,size=size), "booked_perc": np.random.rand(size)})df["id"] = df.index.map(str) +"-" + df.citydf = df[["id", "city", "booked_perc"]]df.head()

1.如何避免對數據求和

翻滾的熊貓/Reddit

來自Java世界的靈感,把“多行for循環”應用到了Python。

計算booked perc列的總和,把百分比加起來毫無意義,但無論如何,一起來試試吧,實踐出真知。

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

更符合Python風格的方式來對列求和如下:

  • %%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循環來過濾數據。求和時,還是可以觀察到性能上的差異。

  • %%timeitsuma = 0for _, row in df.iterrows(): if row.booked_perc <=0.5: 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)

正如預期的一樣,第二個例子比第一個例子快很多

如果加入更多的過濾器呢?只需把它們添加到括號里

  • %%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循環來計算一行到另一行百分數的改變

  • %%timeitfor i inrange(1, len(df)): 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循環

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

一個更好的辦法是直接在Dataframe上使用函數

  • %%timeitdef calculate_sales_factor(row): if row.city =='new york': return row.booked_perc* 2 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過濾器直接計算函數值

  • %%timeit df.loc[df.city== 'new york', 'sales_factor'] = df[df.city == 'newyork'].booked_perc * 2df.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表達式。這比運用函數更快。

  • Eg: f(x, a, b) = (a + b) * xdf['a_plus_b'] = df['a'] +df['b']df['f'] = df['a_plus_b'] * df['x']

5.如何避免對數據進行分組

蹭癢熊貓/Giphy

現在可以看到,在開始使用pandas之前,筆者更多依賴于for循環。至于對數據進行分組,如果充分發揮pandas的優勢,可以減少代碼行數。

要計算如下數據:

一個城市的平均sales factor

一個城市的首次預定id

  • %%timeit avg_by_city = {}count_by_city = {}first_booking_by_city = {}for i, row in df.iterrows(): city = row.city if city in avg_by_city: avg_by_city[city] += row.sales_factor count_by_city[city] += 1 else: avg_by_city[city] = row.sales_factor count_by_city[city] = 1 first_booking_by_city[city] =row['id']for city, _ in avg_by_city.items(): 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語句一樣的。

  • %%timeitdf.groupby('city').sales_factor.mean()df.groupby('city').sales_factor.count()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。

大家一起來試試這些方法吧,一定會有意想不到的收獲~

留言 點贊 關注

我們一起分享AI學習與發展的干貨

如需轉載,請后臺留言,遵守轉載規范

 
 
免責聲明
本文為會員免費發布,僅代表發布者個人觀點,本站未對其內容進行核實,請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內容,一經發現,立即刪除,作者需自行承擔相應責任。涉及到版權或其他問題,請及時聯系我們刪除處理。
 
 
主站蜘蛛池模板: 日韩在线视频二区| 日韩精品视频在线观看视频| 国产欧美综合一区| 国产美女精品免费电影| 美女久久久久久久| 日韩欧美一区二| av免费观看网| 久久综合给合久久狠狠色| 日韩在线视频网站| 亚洲国产成人不卡| 北条麻妃在线一区| 白嫩少妇丰满一区二区| 国产欧美日韩中文| 久久韩国免费视频| 久久在线中文字幕| 日韩亚洲在线视频| 日韩精品视频在线观看视频 | 日韩中文字幕网| 99热在线国产| 91免费视频国产| 国产不卡av在线免费观看| 国产精品久久久一区| 国产成人精品999| 97精品国产91久久久久久| 69av在线视频| 日韩欧美在线播放视频| 青春草国产视频| 久久久久久久免费视频| 久久精品国产v日韩v亚洲 | 国产精品 欧美在线| 高清一区二区三区视频| 亚洲一区在线直播| 日韩精品福利片午夜免费观看| 欧美日韩精品久久久免费观看| 久久亚洲私人国产精品va| 国产素人在线观看| 不卡视频一区二区| 日韩av不卡播放| 久久国产视频网站| 国产人妻互换一区二区| 国产精品尤物福利片在线观看 |