国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Pandas之旅(七) 誰說pandas慢

genedna / 1694人閱讀

摘要:下面讓我們開始提速假設(shè)我們現(xiàn)在的電價是定值,不根據(jù)用電時間段來改變,那么中最快的方法那就是采用,這就是一個簡單的矢量化操作示范。它基本是在中運行最快的方式。

Pandas 加速

大家好,今天我們來看有關(guān)pandas加速的小技巧,不知道大家在剛剛接觸pandas的時候有沒有聽過如下的說法

</>復(fù)制代碼

  1. pandas太慢了,運行要等半天

其實我想說的是,慢不是pandas的錯,大家要知道pandas本身是在Numpy上建立起來的包,在很多情況下是支持向量化運算的,而且還有C的底層設(shè)計,所以我今天
主要想從幾個方面和大家分享一下pandas加速的小技巧,與往常一樣,文章分成四部分,本文結(jié)構(gòu)如下:

使用datetime類型來處理和時間序列有關(guān)的數(shù)據(jù)

批量計算的技巧

通過HDFStore存儲數(shù)據(jù)節(jié)省時間

源碼,相關(guān)數(shù)據(jù)及GitHub地址

現(xiàn)在就讓我們開始吧

1. 使用datetime類型來處理和時間序列有關(guān)的數(shù)據(jù)

首先這里我們使用的數(shù)據(jù)源是一個電力消耗情況的數(shù)據(jù)(energy_cost.csv),非常貼近生活而且也是和時間息息相關(guān)的,用來做測試在合適不過了,這個csv文件大家可以在第四部分找到下載的地方哈

</>復(fù)制代碼

  1. import os
  2. # 這兩行僅僅是切換路徑,方便我上傳Github,大家不用理會,只要確認csv文件和py文件再一起就行啦
  3. os.chdir("F:Python教程segmentfaultpandas_sharePandas之旅_07 誰說pandas慢")

現(xiàn)在讓我們看看數(shù)據(jù)大概長什么樣子

</>復(fù)制代碼

  1. import numpy as np
  2. import pandas as pd
  3. f"Using {pd.__name__},{pd.__version__}"

</>復(fù)制代碼

  1. "Using pandas,0.23.0"

</>復(fù)制代碼

  1. df = pd.read_csv("energy_cost.csv",sep=",")
  2. df.head()
date_time energy_kwh
0 2001/1/13 0:00 0.586
1 2001/1/13 1:00 0.580
2 2001/1/13 2:00 0.572
3 2001/1/13 3:00 0.596
4 2001/1/13 4:00 0.592

現(xiàn)在我們看到初始數(shù)據(jù)的樣子了,主要有date_time和energy_kwh這兩列,來表示時間和消耗的電力,比較好理解,下面讓我們來看一下數(shù)據(jù)類型

</>復(fù)制代碼

  1. df.dtypes
  2. >>> date_time object
  3. energy_kwh float64
  4. dtype: object

</>復(fù)制代碼

  1. type(df.iat[0,0])
  2. >>> str

這里有個小問題,Pandas和NumPy有dtypes(數(shù)據(jù)類型)的概念。如果未指定參數(shù),則date_time這一列的數(shù)據(jù)類型默認object,所以為了之后運算方便,我們可以把str類型的這一列轉(zhuǎn)化為timestamp類型:

</>復(fù)制代碼

  1. df["date_time"] = pd.to_datetime(df["date_time"])
  2. df.dtypes
  3. >>> date_time datetime64[ns]
  4. energy_kwh float64
  5. dtype: object

先在大家可以發(fā)現(xiàn)我們通過用pd.to_datetime這個方法已經(jīng)成功的把date_time這一列轉(zhuǎn)化為了datetime64類型

</>復(fù)制代碼

  1. df.head()
date_time energy_kwh
0 2001-01-13 00:00:00 0.586
1 2001-01-13 01:00:00 0.580
2 2001-01-13 02:00:00 0.572
3 2001-01-13 03:00:00 0.596
4 2001-01-13 04:00:00 0.592

現(xiàn)在再來看數(shù)據(jù), 發(fā)現(xiàn)已經(jīng)和剛才不同了,我們還可以通過指定format參數(shù)實現(xiàn)一樣的效果,速度上也會快一些

</>復(fù)制代碼

  1. %%timeit -n 10
  2. def convert_with_format(df, column_name):
  3. return pd.to_datetime(df[column_name],format="%Y/%m/%d %H:%M")
  4. df["date_time"]=convert_with_format(df, "date_time")
  5. >>>722 μs ± 334 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)

有關(guān)具體的日期自定義相關(guān)方法,大家點擊這里查看

2. 批量計算的技巧

首先,我們假設(shè)根據(jù)用電的時間段不同,電費價目表如下:

Type cents/kwh periode
Peak 28 17:00 to 24:00
Shoulder 20 7:00 to 17:00
Off-Peak 12 0:00 to 7:00

假設(shè)我們想要計算出電費,我們可以先寫出一個根據(jù)時間動態(tài)計算電費的方法“apply_tariff“

</>復(fù)制代碼

  1. def apply_tariff(kwh, hour):
  2. """Calculates cost of electricity for given hour."""
  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

好啦,現(xiàn)在我們想要在數(shù)據(jù)中新增一列 "cost_cents" 來表示總價錢,我們有很多選擇,首先能想到的方法便是iterrows(),它可以讓我們循環(huán)遍歷Dataframe的每一行,根據(jù)條件計算并賦值給新增的‘cost_cents’列

iterrows()

首先我們能做的是循環(huán)遍歷流程,讓我們先用.iterrows()替代上面的方法來試試:

</>復(fù)制代碼

  1. %%timeit -n 10
  2. def apply_tariff_iterrows(df):
  3. energy_cost_list = []
  4. for index, row in df.iterrows():
  5. # Get electricity used and hour of day
  6. energy_used = row["energy_kwh"]
  7. hour = row["date_time"].hour
  8. # Append cost list
  9. energy_cost = apply_tariff(energy_used, hour)
  10. energy_cost_list.append(energy_cost)
  11. df["cost_cents"] = energy_cost_list
  12. apply_tariff_iterrows(df)

</>復(fù)制代碼

  1. 983 ms ± 65.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

我們?yōu)榱藴y試方便,所有的方法都會循環(huán)10次來比較耗時,這里很明顯我們有很大的改進空間,下面我們用apply方法來優(yōu)化

apply()

</>復(fù)制代碼

  1. %%timeit -n 10
  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. apply_tariff_withapply(df)

</>復(fù)制代碼

  1. 247 ms ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

這回速度得到了很大的提升,但是顯然我們還沒有g(shù)et到pandas加速的精髓:矢量化操作。下面讓我們開始提速

isin()

假設(shè)我們現(xiàn)在的電價是定值,不根據(jù)用電時間段來改變,那么pandas中最快的方法那就是采用(df["cost_cents"] = df["energy_kwh"] * price),這就是一個簡單的矢量化操作示范。它基本是在Pandas中運行最快的方式。

目前的問題是我們的價格是動態(tài)的,那么如何將條件判斷添加到Pandas中的矢量化運算中呢?答案就是我們根據(jù)條件選擇和分組DataFrame,然后對每個選定的組應(yīng)用矢量化操作:

</>復(fù)制代碼

  1. #先讓我們把時間序列作為索引
  2. df.set_index("date_time", inplace=True)

</>復(fù)制代碼

  1. %%timeit -n 10
  2. def apply_tariff_isin(df):
  3. # Define hour range Boolean arrays
  4. peak_hours = df.index.hour.isin(range(17, 24))
  5. shoulder_hours = df.index.hour.isin(range(7, 17))
  6. off_peak_hours = df.index.hour.isin(range(0, 7))
  7. # Apply tariffs to hour ranges
  8. df.loc[peak_hours, "cost_cents"] = df.loc[peak_hours, "energy_kwh"] * 28
  9. df.loc[shoulder_hours,"cost_cents"] = df.loc[shoulder_hours, "energy_kwh"] * 20
  10. df.loc[off_peak_hours,"cost_cents"] = df.loc[off_peak_hours, "energy_kwh"] * 12
  11. apply_tariff_isin(df)

</>復(fù)制代碼

  1. 5.7 ms ± 871 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)

這回我們發(fā)現(xiàn)速度是真正起飛了,首先我們根據(jù)用電的三個時段把df進行分三組,再依次進行三次矢量化操作,大家可以發(fā)現(xiàn)最后減少了很多時間,原理很簡單:

在運行的時候,.isin()方法返回一個布爾值數(shù)組,如下所示:

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

接下來布爾數(shù)組傳遞給DataFrame的.loc索引器時,我們獲得一個僅包含與3個用電時段匹配DataFrame切片。然后簡單的進行乘法操作就行了,這樣做的好處是我們已經(jīng)不需要剛才提過的apply方法了,因為不在存在遍歷所有行的問題

我們可以做的更好嗎?

通過觀察可以發(fā)現(xiàn),在apply_tariff_isin()中,我們?nèi)匀辉谕ㄟ^調(diào)用df.loc和df.index.hour.isin()來進行一些“手動工作”。如果想要進一步提速,我們可以使用cut方法

</>復(fù)制代碼

  1. %%timeit -n 10
  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"]

</>復(fù)制代碼

  1. 140 ns ± 29.9 ns per loop (mean ± std. dev. of 7 runs, 10 loops each)

效果依然鋒利,速度上有了成倍的提升

不要忘了用Numpy

眾所周知,Pandas是在Numpy上建立起來的,所以在Numpy中當(dāng)然有類似cut的方法可以實現(xiàn)分組,從速度上來講差不太多

</>復(fù)制代碼

  1. %%timeit -n 10
  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

</>復(fù)制代碼

  1. 54.9 ns ± 19.3 ns per loop (mean ± std. dev. of 7 runs, 10 loops each)

正常情況下,以上的加速方法是能滿足日常需要的,如果有特殊的需求,大家可以上網(wǎng)看看有沒有相關(guān)的第三方加速包

3. 通過HDFStore存儲數(shù)據(jù)節(jié)省時間

這里主要想強調(diào)的是節(jié)省預(yù)處理的時間,假設(shè)我們辛辛苦苦搭建了一些模型,但是每次運行之前都要進行一些預(yù)處理,比如類型轉(zhuǎn)換,用時間序列做索引等,如果不用HDFStore的話每次都會花去不少時間,這里Python提供了一種解決方案,可以把經(jīng)過預(yù)處理的數(shù)據(jù)存儲為HDF5格式,方便我們下次運行時直接調(diào)用。

下面就讓我們把本篇文章的df通過HDF5來存儲一下:

</>復(fù)制代碼

  1. # Create storage object with filename `processed_data`
  2. data_store = pd.HDFStore("processed_data.h5")
  3. # Put DataFrame into the object setting the key as "preprocessed_df"
  4. data_store["preprocessed_df"] = df
  5. data_store.close()

現(xiàn)在我們可以關(guān)機下班了,當(dāng)明天接著上班后,通過key("preprocessed_df")就可以直接使用經(jīng)過預(yù)處理的數(shù)據(jù)了

</>復(fù)制代碼

  1. # Access data store
  2. data_store = pd.HDFStore("processed_data.h5")
  3. # Retrieve data using key
  4. preprocessed_df = data_store["preprocessed_df"]
  5. data_store.close()

</>復(fù)制代碼

  1. preprocessed_df.head()
energy_kwh cost_cents
date_time
2001-01-13 00:00:00 0.586 7.032
2001-01-13 01:00:00 0.580 6.960
2001-01-13 02:00:00 0.572 6.864
2001-01-13 03:00:00 0.596 7.152
2001-01-13 04:00:00 0.592 7.104

如上圖所示,現(xiàn)在我們可以發(fā)現(xiàn)date_time已經(jīng)是處理為index了

4. 源碼,相關(guān)數(shù)據(jù)及GitHub地址

這一期為大家分享了一些pandas加速的實用技巧,希望可以幫到各位小伙伴,當(dāng)然,類似的技巧還有很多,但是核心思想應(yīng)該一直圍繞矢量化操作上,畢竟是基于Numpy上建立的包,如果大家有更好的辦法,希望可以在我的文章底下留言哈

我把這一期的ipynb文件,py文件以及我們用到的energy_cost.csv放到了Github上,大家可以點擊下面的鏈接來下載:

Github倉庫地址: https://github.com/yaozeliang/pandas_share

希望大家能夠繼續(xù)支持我,這一篇文章已經(jīng)是Pandas系列的最后一篇了,雖然一共只寫了7篇文章,但是我認為從實用性上來講并沒有太遜色于收費課程(除了少了很多漂亮的ppt),接下來我會再接再厲,分享一下我對R (ggplot2)或者matplotlib的學(xué)習(xí)經(jīng)驗?。?/p>

Pandas之旅到此結(jié)束。撒花

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/43518.html

相關(guān)文章

  • Pandas之旅(三)最實用的Merge, Join,Concat方法詳解

    摘要:基于上的我們還可以實現(xiàn)幾個基于的,還是老樣子,先讓我們創(chuàng)建兩個好了,現(xiàn)在我們想要實現(xiàn)兩個的,但是條件是通過的和的這樣我們也可以得到結(jié)果。 Merge, Join, Concat 大家好,我有回來啦,這周更新的有點慢,主要是因為我更新了個人簡歷哈哈,如果感興趣的朋友可以去看看哈: 我的主頁 個人認為還是很漂亮的~,不得不說,很多時候老外的設(shè)計能力還是很強。 好了,有點扯遠了,這一期我想和...

    CloudwiseAPM 評論0 收藏0
  • Pandas之旅(四) : 可能是社區(qū)內(nèi)最實用的Pandas技巧

    摘要:不為人知的七大實用技巧大家好,我今天勤快地回來了,這一期主要是和大家分享一些的實用技巧,會在日常生活中大大提升效率,希望可以幫助到大家還是老樣子,先給大家奉上這一期的章節(jié)目錄自定義選項,設(shè)置實用中模塊構(gòu)建測試數(shù)據(jù)巧用訪問器合并其他列拼接使用 Pandas不為人知的七大實用技巧 大家好,我今天勤快地回來了,這一期主要是和大家分享一些pandas的實用技巧,會在日常生活中大大提升效率,希望...

    iflove 評論0 收藏0
  • Pandas之旅(一): 讓我們把基礎(chǔ)知識一次擼完,申精干貨

    為什么你需要pandas 大家好,今天想和大家分享一下有關(guān)pandas的學(xué)習(xí)新的,我因工作需要,從去年12月開始接觸這個非常好用的包,到現(xiàn)在為止也是算是熟悉了一些,因此發(fā)現(xiàn)了它的強大之處,特意想要和朋友們分享,特別是如果你每天和excel打交道,總是需要編寫一些vba函數(shù)或者對行列進行g(shù)roupby啊,merge,join啊之類的,相信我,pandas會讓你解脫的。 好啦,閑話少說,這篇文章的基礎(chǔ)...

    tuomao 評論0 收藏0
  • Pandas之旅(二): 有關(guān)數(shù)據(jù)清理的點點滴滴

    摘要:數(shù)據(jù)清洗大家好,這一期我將為大家?guī)砦业膶W(xué)習(xí)心得第二期數(shù)據(jù)清理。這一期我會和大家分享一些比較好用常見的清洗方法。首先還是讓我們來簡單看一下本文將會用到的數(shù)據(jù)源這是一個超小型的房地產(chǎn)行業(yè)的數(shù)據(jù)集,大家會在文章最后找到下載地址。 數(shù)據(jù)清洗 大家好,這一期我將為大家?guī)砦业膒andas學(xué)習(xí)心得第二期:數(shù)據(jù)清理。這一步非常重要,一般在獲取數(shù)據(jù)源之后,我們緊接著就要開始這一步,以便為了之后的各種...

    wenyiweb 評論0 收藏0
  • Pandas之旅(六): 字符串實用方法匯總

    摘要:有關(guān)字符串基本方法大家好,我又回來了之前的幾期我們已經(jīng)簡單了解了的基礎(chǔ)操作,但是只要涉及到數(shù)據(jù),最常見的就是字符串類型,所以很多時候我們其實都在和字符串打交道,所以今天,我會把我自己總結(jié)的,有關(guān)字符串的常用方法分享給大家,希望能夠幫到各位小 有關(guān)字符串基本方法 大家好,我又回來了! 之前的幾期我們已經(jīng)簡單了解了pandas的基礎(chǔ)操作,但是只要涉及到數(shù)據(jù),最常見的就是String(字符串...

    高勝山 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<