国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

再見for循環(huán)!pandas提速315倍~

開發(fā) 后端
本次東哥介紹幾個常見的提速方法,一個比一個快,了解pandas本質(zhì),才能知道如何提速。

 for是所有編程語言的基礎(chǔ)語法,初學(xué)者為了快速實現(xiàn)功能,依懶性較強。但如果從運算時間性能上考慮可能不是特別好的選擇。

本次東哥介紹幾個常見的提速方法,一個比一個快,了解pandas本質(zhì),才能知道如何提速。

下面是一個例子,數(shù)據(jù)獲取方式見文末。 

  1. >>> import pandas as pd  
  2. # 導(dǎo)入數(shù)據(jù)集  
  3. >>> df = pd.read_csv('demand_profile.csv')  
  4. >>> df.head()  
  5.      date_time  energy_kwh  
  6. 0  1/1/13 0:00       0.586  
  7. 1  1/1/13 1:00       0.580  
  8. 2  1/1/13 2:00       0.572  
  9. 3  1/1/13 3:00       0.596  
  10. 4  1/1/13 4:00       0.592 

基于上面的數(shù)據(jù),我們現(xiàn)在要增加一個新的特征,但這個新的特征是基于一些時間條件生成的,根據(jù)時長(小時)而變化,如下:

因此,如果你不知道如何提速,那正常第一想法可能就是用apply方法寫一個函數(shù),函數(shù)里面寫好時間條件的邏輯代碼。 

  1. def apply_tariff(kwh, hour):  
  2.     """計算每個小時的電費"""      
  3.     if 0 <= hour < 7:  
  4.         rate = 12  
  5.     elif 7 <= hour < 17:  
  6.         rate = 20  
  7.     elif 17 <= hour < 24:  
  8.         rate = 28  
  9.     else:  
  10.         raise ValueError(f'Invalid hour: {hour}')  
  11.     return rate * kwh 

然后使用for循環(huán)來遍歷df,根據(jù)apply函數(shù)邏輯添加新的特征,如下: 

  1. >>> # 不贊同這種操作  
  2. >>> @timeit(repeat=3number=100 
  3. ... def apply_tariff_loop(df): 
  4. ...     """用for循環(huán)計算enery cost,并添加到列表"""  
  5. ...     energy_cost_list = []  
  6. ...     for i in range(len(df)):  
  7. ...         # 獲取用電量和時間(小時)  
  8. ...         energy_used = df.iloc[i]['energy_kwh']  
  9. ...         hour = df.iloc[i]['date_time'].hour  
  10. ...         energy_cost = apply_tariff(energy_used, hour)  
  11. ...         energy_cost_list.append(energy_cost)  
  12. ...     df['cost_cents'] = energy_cost_list  
  13. ...   
  14. >>> apply_tariff_loop(df)  
  15. Best of 3 trials with 100 function calls per trial:  
  16. Function `apply_tariff_loop` ran in average of 3.152 seconds. 

對于那些寫Pythonic風(fēng)格的人來說,這個設(shè)計看起來很自然。然而,這個循環(huán)將會嚴(yán)重影響效率。原因有幾個:

首先,它需要初始化一個將記錄輸出的列表。

其次,它使用不透明對象范圍(0,len(df))循環(huán),然后再應(yīng)用apply_tariff()之后,它必須將結(jié)果附加到用于創(chuàng)建新DataFrame列的列表中。另外,還使用df.iloc [i]['date_time']執(zhí)行所謂的鏈?zhǔn)剿饕@通常會導(dǎo)致意外的結(jié)果。

這種方法的最大問題是計算的時間成本。對于8760行數(shù)據(jù),此循環(huán)花費了3秒鐘。

接下來,一起看下優(yōu)化的提速方案。

[[381980]]

使用 iterrows循環(huán)

第一種可以通過pandas引入iterrows方法讓效率更高。這些都是一次產(chǎn)生一行的生成器方法,類似scrapy中使用的yield用法。

.itertuples為每一行產(chǎn)生一個namedtuple,并且行的索引值作為元組的第一個元素。nametuple是Python的collections模塊中的一種數(shù)據(jù)結(jié)構(gòu),其行為類似于Python元組,但具有可通過屬性查找訪問的字段。

.iterrows為DataFrame中的每一行產(chǎn)生(index,series)這樣的元組。

在這個例子中使用.iterrows,我們看看這使用iterrows后效果如何。 

  1. >>> @timeit(repeat=3number=100 
  2. ... def apply_tariff_iterrows(df):  
  3. ...     energy_cost_list = []  
  4. ...     for index, row in df.iterrows():  
  5. ...         # 獲取用電量和時間(小時)  
  6. ...         energy_used = row['energy_kwh']  
  7. ...         hour = row['date_time'].hour  
  8. ...         # 添加cost列表  
  9. ...         energy_cost = apply_tariff(energy_used, hour)  
  10. ...         energy_cost_list.append(energy_cost)  
  11. ...     df['cost_cents'] = energy_cost_list  
  12. ...  
  13. >>> apply_tariff_iterrows(df)  
  14. Best of 3 trials with 100 function calls per trial:  
  15. Function `apply_tariff_iterrows` ran in average of 0.713 seconds. 

這樣的語法更明確,并且行值引用中的混亂更少,因此它更具可讀性。

時間成本方面:快了近5倍!

但是,還有更多的改進空間,理想情況是可以用pandas內(nèi)置更快的方法完成。

[[381981]]

pandas的apply方法

我們可以使用.apply方法而不是.iterrows進一步改進此操作。pandas的.apply方法接受函數(shù)callables并沿DataFrame的軸(所有行或所有列)應(yīng)用。下面代碼中,lambda函數(shù)將兩列數(shù)據(jù)傳遞給apply_tariff(): 

  1. >>> @timeit(repeat=3number=100 
  2. ... def apply_tariff_withapply(df):  
  3. ...     df['cost_cents'] = df.apply(  
  4. ...         lambda row: apply_tariff(  
  5. ...             kwh=row['energy_kwh'],  
  6. ...             hour=row['date_time'].hour),  
  7. ...         axis=1 
  8. ...  
  9. >>> apply_tariff_withapply(df)  
  10. Best of 3 trials with 100 function calls per trial:  
  11. Function `apply_tariff_withapply` ran in average of 0.272 seconds. 

apply的語法優(yōu)點很明顯,行數(shù)少,代碼可讀性高。在這種情況下,所花費的時間大約是iterrows方法的一半。

但是,這還不是“非常快”。一個原因是apply()將在內(nèi)部嘗試循環(huán)遍歷Cython迭代器。但是在這種情況下,傳遞的lambda不是可以在Cython中處理的東西,因此它在Python中調(diào)用并不是那么快。

如果我們使用apply()方法獲取10年的小時數(shù)據(jù),那么將需要大約15分鐘的處理時間。如果這個計算只是大規(guī)模計算的一小部分,那么真的應(yīng)該提速了。這也就是矢量化操作派上用場的地方。

 

[[381982]]

矢量化操作:使用.isin選擇數(shù)據(jù)

什么是矢量化操作?

如果你不基于一些條件,而是可以在一行代碼中將所有電力消耗數(shù)據(jù)應(yīng)用于該價格:df ['energy_kwh'] * 28,類似這種。那么這個特定的操作就是矢量化操作的一個例子,它是在pandas中執(zhí)行的最快方法。

但是如何將條件計算應(yīng)用為pandas中的矢量化運算?

一個技巧是:根據(jù)你的條件,選擇和分組DataFrame,然后對每個選定的組應(yīng)用矢量化操作。

在下面代碼中,我們將看到如何使用pandas的.isin()方法選擇行,然后在矢量化操作中實現(xiàn)新特征的添加。在執(zhí)行此操作之前,如果將date_time列設(shè)置為DataFrame的索引,會更方便: 

  1. # 將date_time列設(shè)置為DataFrame的索引  
  2. df.set_index('date_time', inplace=True 
  3. @timeit(repeat=3number=100 
  4. def apply_tariff_isin(df):  
  5.     # 定義小時范圍Boolean數(shù)組  
  6.     peak_hours = df.index.hour.isin(range(17, 24))  
  7.     shoulder_hours = df.index.hour.isin(range(7, 17))  
  8.     off_peak_hours = df.index.hour.isin(range(0, 7)) 
  9.     # 使用上面apply_traffic函數(shù)中的定義  
  10.     df.loc[peak_hours, 'cost_cents'] = df.loc[peak_hours, 'energy_kwh'] * 28  
  11.     df.loc[shoulder_hours,'cost_cents'] = df.loc[shoulder_hours, 'energy_kwh'] * 20  
  12.     df.loc[off_peak_hours,'cost_cents'] = df.loc[off_peak_hours, 'energy_kwh'] * 12 

我們來看一下結(jié)果如何。 

  1. >>> apply_tariff_isin(df)  
  2. Best of 3 trials with 100 function calls per trial:  
  3. Function `apply_tariff_isin` ran in average of 0.010 seconds. 

提示,上面.isin()方法返回的是一個布爾值數(shù)組,如下: 

  1. [False, False, False, ..., True, True, True] 

布爾值標(biāo)識了DataFrame索引datetimes是否落在了指定的小時范圍內(nèi)。然后把這些布爾數(shù)組傳遞給DataFrame的.loc,將獲得一個與這些小時匹配的DataFrame切片。然后再將切片乘以適當(dāng)?shù)馁M率,這就是一種快速的矢量化操作了。

上面的方法完全取代了我們最開始自定義的函數(shù)apply_tariff(),代碼大大減少,同時速度起飛。

運行時間比Pythonic的for循環(huán)快315倍,比iterrows快71倍,比apply快27倍!

[[381983]]

還能更快?

太刺激了,我們繼續(xù)加速。

在上面apply_tariff_isin中,我們通過調(diào)用df.loc和df.index.hour.isin三次來進行一些手動調(diào)整。如果我們有更精細(xì)的時間范圍,你可能會說這個解決方案是不可擴展的。但在這種情況下,我們可以使用pandas的pd.cut()函數(shù)來自動完成切割: 

  1. @timeit(repeat=3number=100 
  2. def apply_tariff_cut(df):  
  3.     cents_per_kwh = pd.cut(x=df.index.hour,  
  4.                            bins=[0, 7, 17, 24],  
  5.                            include_lowest=True 
  6.                            labels=[12, 20, 28]).astype(int)  
  7.     df['cost_cents'] = cents_per_kwh * df['energy_kwh'] 

上面代碼pd.cut()會根據(jù)bin列表應(yīng)用分組。

其中include_lowest參數(shù)表示第一個間隔是否應(yīng)該是包含左邊的。

這是一種完全矢量化的方法,它在時間方面是最快的: 

  1. >>> apply_tariff_cut(df)  
  2. Best of 3 trials with 100 function calls per trial:  
  3. Function `apply_tariff_cut` ran in average of 0.003 seconds. 

到目前為止,使用pandas處理的時間上基本快達(dá)到極限了!只需要花費不到一秒的時間即可處理完整的10年的小時數(shù)據(jù)集。

但是,最后一個其它選擇,就是使用 NumPy,還可以更快!

[[381984]]

使用Numpy繼續(xù)加速

使用pandas時不應(yīng)忘記的一點是Pandas的Series和DataFrames是在NumPy庫之上設(shè)計的。并且,pandas可以與NumPy陣列和操作無縫銜接。

下面我們使用NumPy的 digitize()函數(shù)更進一步。它類似于上面pandas的cut(),因為數(shù)據(jù)將被分箱,但這次它將由一個索引數(shù)組表示,這些索引表示每小時所屬的bin。然后將這些索引應(yīng)用于價格數(shù)組: 

  1. @timeit(repeat=3number=100 
  2. def apply_tariff_digitize(df):  
  3.     prices = np.array([12, 20, 28])  
  4.     bins = np.digitize(df.index.hour.values, bins=[7, 17, 24])  
  5.     df['cost_cents'] = prices[bins] * df['energy_kwh'].values 

與cut函數(shù)一樣,這種語法非常簡潔易讀。 

  1. >>> apply_tariff_digitize(df)  
  2. Best of 3 trials with 100 function calls per trial:  
  3. Function `apply_tariff_digitize` ran in average of 0.002 seconds. 

0.002秒! 雖然仍有性能提升,但已經(jīng)很邊緣化了。 

 

責(zé)任編輯:龐桂玉 來源: AI科技大本營
相關(guān)推薦

2021-01-13 11:13:46

ExcelPandas代碼

2019-09-02 15:12:46

Python 開發(fā)數(shù)據(jù)分析

2020-09-27 11:15:37

可視化PandasPython

2024-01-03 15:50:33

Python循環(huán)測試

2023-12-10 14:06:04

數(shù)據(jù)庫pythonduckdb

2016-10-08 16:02:37

WIFIMegaMIMO系統(tǒng)

2019-08-27 17:32:10

數(shù)據(jù)處理PandasPython

2023-01-05 11:34:46

PandasMerge方法

2016-03-21 10:16:06

RedisSpark大數(shù)據(jù)處理

2013-02-28 10:35:59

hadoop大數(shù)據(jù)Hortonworks

2022-08-09 09:10:31

TaichiPython

2016-02-18 09:36:52

光纖wifi

2009-12-16 11:43:28

卡巴斯基NVIDIA Tesl

2013-09-24 09:40:41

Java圖形加速

2025-11-26 07:00:00

Python循環(huán)開發(fā)

2021-09-08 08:00:00

PyPolars數(shù)據(jù)開源

2018-03-28 14:10:10

GoPython代碼

2013-10-17 09:34:56

企業(yè)郵箱海外訪問提速

2020-05-01 12:35:31

C++Python編程

2024-10-16 09:34:50

點贊
收藏

51CTO技術(shù)棧公眾號

超碰精品在线观看| 日韩欧美2区| 少妇性l交大片| 精品欧美一区二区在线观看视频 | 95精品视频| 欧美一级淫片| 亚洲第一精品自拍| 中文字幕在线观看一区| 国产一区二区三区黄视频| 影院欧美亚洲| 欧美色蜜桃97| 丁香综合av| 国产成+人+综合+亚洲欧美| 国产蜜臀在线| 国产在线激情视频| 国产免费av高清在线| 97国产在线| 97福利电影| 欧美精品99久久| 日韩中文字幕亚洲精品欧美| 欧美日韩电影一区二区三区| 成人xxxxx色| 国产精品一二三视频| 欧美性一区二区三区| 久久不射电影网| 色婷婷av一区二区三区久久| 日韩av综合中文字幕| 日韩欧美高清一区| 欧美美女网站色| 欧美性生活大片视频| 精品久久久久久国产| 亚洲一区二区视频在线| 最新成人av在线| 国产精品不卡在线| 中文字幕中文字幕中文字幕亚洲无线| 久久日一线二线三线suv| 成人国产精品免费观看动漫| 国产一二精品视频| 国产又粗又猛又爽又黄91精品| 日韩高清中文字幕一区| 久久免费国产| 丝袜美腿亚洲色图| 久久激情网站| 在线亚洲一区| 久久精品主播| 日韩av成人高清| 免费精品视频在线| 精品一区在线看| 国产经典欧美精品| 成人性色生活片免费看爆迷你毛片| 国产91丝袜在线播放| 不卡在线观看av| 91丨porny丨户外露出| 国产人成一区二区三区影院| 国产日韩成人精品| 亚洲欧美日韩中文字幕一区二区三区| 中文字幕第一区二区| 日韩美女啊v在线免费观看| 亚洲黄色小说网站| 午夜久久久影院| 一本大道av伊人久久综合| 91国产精品成人| 在线综合视频播放| 亚洲精品成人网| 最新国产成人av网站网址麻豆| 久久久精品一区二区三区| 欧美激情一区二区久久久| 欧美性视频在线| 91在线观看免费| 久久婷婷开心| 日本a级片在线观看| 亚洲乱码中文字幕久久孕妇黑人| 少妇一级淫免费放| 新欧美整片sss第一页| 免费日本一区二区三区视频| 黄色污污视频在线观看| 蜜桃成人精品| 成人av资源网址| 日韩一区二区三区免费播放| 亚洲一级特黄| 精品一区二区日韩| 国产亚洲视频系列| 亚洲第一激情av| 7777精品伊人久久久大香线蕉超级流畅 | 黄色毛片视频| 青青青草原在线| 色呦呦呦在线观看| 欧美视频免费看| 久久最新网址| 日韩一区二区久久| 国产69精品久久久久777| 国产日韩欧美不卡在线| 午夜精品免费在线观看| 91精品蜜臀在线一区尤物| 国产午夜精品一区理论片飘花| 欧美激情久久久久| 亚洲www永久成人夜色| 色姑娘综合网| 三级在线免费看| 在线免费看黄色| а√在线天堂官网| 97精品久久| 亚洲第一伊人| 国产成a人无v码亚洲福利| 亚洲男人的天堂av| 日韩天堂在线观看| 欧美富婆性猛交| y111111国产精品久久婷婷| 一二三在线视频| 免费特级黄毛片| 久久久久黄久久免费漫画| 最新亚洲国产| 911久久香蕉国产线看观看| 国内外成人在线| 玉米视频成人免费看| 日韩欧美的一区| 久久免费国产精品1| 久久99精品久久久久久青青日本 | 中文字幕视频在线| 97超碰免费在线| 老汉色老汉首页av亚洲| 日韩视频不卡| 久久女同精品一区二区| 日本乱人伦一区| yw.139尤物在线精品视频| 国产精品一区久久久| 大桥未久一区二区| 中文字字幕在线中文乱码电影| 中文在线最新版地址| 不卡视频在线| 国产91精品露脸国语对白| 欧美日韩美女在线| 国产一区二区精品丝袜| 91精品国产自产在线老师啪| 日韩a级黄色片| 理论视频在线| 视频精品一区二区三区| 一本色道88久久加勒比精品| 国产亚洲一区字幕| 日韩欧美卡一卡二| 日韩美女福利视频| 成人国产在线看| 国产视频网址在线| 77成人影视| 麻豆久久一区二区| 午夜电影一区二区三区| 俺去亚洲欧洲欧美日韩| 久久天天狠狠| 女人体1963| 日本精品网站| 激情久久综合| 亚洲啪啪综合av一区二区三区| 日韩电影大片中文字幕| 亚洲伊人久久大香线蕉av| 日本熟妇人妻xxxxx| 色呦呦视频在线观看| 色婷婷亚洲mv天堂mv在影片| 91亚洲精品久久久蜜桃| 日韩欧美亚洲另类制服综合在线| 国产精品久久久久99| 中文字幕人妻熟女人妻洋洋| 91caoporn在线| 亚洲肉体裸体xxxx137| 国产91丝袜在线播放九色| 欧美日韩国产综合草草| 国产成人av在线| www国产黄色| 成av人片在线观看www| 亚洲欧美一区在线| 亚洲视频一二三| 色老头一区二区三区| 神马影院午夜我不卡| 蜜桃免费在线| 在线亚洲a色| 久久久亚洲国产美女国产盗摄| 亚洲第一页自拍| 国产福利久久| 97香蕉久久| 极品尤物一区| av电影在线观看一区| 亚洲国产欧美一区二区三区久久| 91传媒视频免费| 日本xxxx高清色视频| 日韩在线亚洲| 成人午夜电影久久影院| 亚洲第一页自拍| 久久久久国产精品视频| 一级在线视频| 国产欧美亚洲精品a| 日本一区二区三区在线不卡| 中文字幕国产日韩| 亚洲伊人婷婷| 手机在线免费av| 日韩亚洲精品在线| 欧美天天综合色影久久精品| 国产91精品网站| 视色视频在线观看| 日韩区欧美区| 久久先锋资源网| 精品国内亚洲在观看18黄|