溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么避免編寫pandas代碼

發(fā)布時間:2021-11-05 14:57:46 來源:億速云 閱讀:137 作者:iii 欄目:web開發(fā)

本篇內(nèi)容主要講解“怎么避免編寫pandas代碼”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“怎么避免編寫pandas代碼”吧!

設(shè)置

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

樣本數(shù)據(jù)集

樣本數(shù)據(jù)集包含各個城市的預(yù)訂信息,是隨機(jī)的,唯一目的是展示樣本。

數(shù)據(jù)集有三列:

  • id表示唯一的標(biāo)識

  • city表示預(yù)定的城市信息

  • booked perc表示特定時間預(yù)定的百分比

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

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

怎么避免編寫pandas代碼

1. 如何避免對數(shù)據(jù)求和

來自Java世界的靈感,把“多行for循環(huán)”應(yīng)用到了Python。

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

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

更符合Python風(fēng)格的方式來對列求和如下:

%%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)

正如預(yù)期的那樣,第一個示例是最慢的——對一萬項(xiàng)求和幾乎需要1秒。第二個例子的速度之快令人驚訝。

正確的方法是使用pandas對數(shù)據(jù)進(jìn)行求和(或?qū)α惺褂萌魏纹渌僮?,這是第三個示例——也是最快的!

2. 如何避免過濾數(shù)據(jù)

盡管在使用pandas之前,筆者已經(jīng)很熟悉numpy,并使用for循環(huán)來過濾數(shù)據(jù)。求和時,還是可以觀察到性能上的差異。

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

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

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

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

3. 如何避免訪問以前的值

你可能會說:好吧,但是如果需要訪問先前某一列的值呢,還是需要一個for循環(huán)。你錯了!

分別使用和不使用for循環(huán)來計算一行到另一行百分?jǐn)?shù)的改變

%%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 &plusmn; 24.4 ms per loop (mean &plusmn; std. dev. of 7runs, 1 loop each)%%timeitdf["perc_change"] = df.booked_perc.pct_change()586&micro;s &plusmn; 17.3 &micro;s per loop (mean &plusmn; std. dev. of 7 runs, 1000 loops each)

同樣,第二個例子比第一個使用for循環(huán)的例子快得多。

pandas有許多函數(shù)可以根據(jù)以前的值計算統(tǒng)計數(shù)據(jù)(例如shift函數(shù)對值進(jìn)行移位)。這些函數(shù)接受periods參數(shù),可以在計算中包含以前值的數(shù)量。

4. 如何避免使用復(fù)雜的函數(shù)

有時需要在DataFrame中使用復(fù)雜函數(shù)(有多個變量的函數(shù))。讓我們將從紐約的booking_perc兩兩相乘,其他設(shè)置為0并且把這列命名為sales_factor。

筆者首先想到的是使用iterrows的for循環(huán)。

%%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 &plusmn; 48.2 ms per loop (mean &plusmn; std. dev. of 7 runs, 1 loop each)

一個更好的辦法是直接在DataFrame上使用函數(shù)。

%%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 &plusmn; 2.48 ms per loop(mean &plusmn; std. dev. of 7 runs, 10 loops each)

最快的方法是使用pandas過濾器直接計算函數(shù)值。

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

可以看到從第一個例子到最后一個的加速過程。

當(dāng)解決有3個及3個以上變量的函數(shù)時,可以把它分解為多個pandas表達(dá)式。這比運(yùn)用函數(shù)更快。

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

5. 如何避免對數(shù)據(jù)進(jìn)行分組

現(xiàn)在可以看到,在開始使用pandas之前,筆者更多依賴于for循環(huán)。至于對數(shù)據(jù)進(jìn)行分組,如果充分發(fā)揮pandas的優(yōu)勢,可以減少代碼行數(shù)。

要計算如下數(shù)據(jù):

  • 一個城市的平均sales factor

  • 一個城市的首次預(yù)定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 &plusmn; 21.4 ms per loop (mean &plusmn; std. dev. of 7 runs, 1 loopeach)

Pandas有分組操作所以不必在DataFrame上進(jìn)行迭代,pandas的分組操作和SQL的GROUP BY語句一樣的。

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

到此,相信大家對“怎么避免編寫pandas代碼”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI