在數(shù)據(jù)分析相關(guān)的工作中,Pandas
無疑是一個(gè)強(qiáng)大的工具,它的易用性和靈活性廣受青睞。
然而,隨著數(shù)據(jù)量的不斷增長和計(jì)算需求的日益復(fù)雜,Pandas
代碼的性能問題也逐漸浮出水面。
如何讓Pandas
代碼運(yùn)行得更快、更高效,成為了每一個(gè)人使用者都需要面對(duì)的挑戰(zhàn)。
今天,本文就一個(gè)簡化版的實(shí)際分析案例,來一起探討Pandas
代碼如何寫才能性能更好,讓你的數(shù)據(jù)處理流程更加順滑,不再為漫長的等待運(yùn)行而煩惱。
1. 案例介紹
假設(shè)有個(gè)股票分析的場景,我們需要給所有的股票每天的交易情況做一個(gè)評(píng)估,評(píng)估的結(jié)果有3個(gè)級(jí)別:優(yōu),中,差。
其中,“優(yōu)”的條件是當(dāng)天成交額大于10億且收盤價(jià)大于開盤價(jià),也就是股票上漲;
“差”的條件是當(dāng)天成交額小于1億且收盤價(jià)小于開盤價(jià),也就是股票下跌;
除此之外的情況就是“中”。
再次強(qiáng)調(diào)一下,這是一個(gè)簡化的評(píng)估方法,主要是為了下面演示Pandas的代碼性能,真實(shí)的評(píng)估不會(huì)如此粗糙。
股票交易的數(shù)據(jù)來自A股2024年1,2月份的日交易數(shù)據(jù),大約20多萬條。
數(shù)據(jù)可從地址 https://databook.top/stock/2024 下載。
導(dǎo)入數(shù)據(jù):
import pandas as pd
# 這個(gè)路徑根據(jù)實(shí)際情況修改
fp = r'D:\data\2024\歷史行情數(shù)據(jù)-東財(cái)-不復(fù)權(quán)-2024.csv'
df = pd.read_csv(fp)
df = df.loc[:, ["股票代碼", "日期", "開盤", "收盤", "最高", "最低", "成交量"]]
df
2. 不同寫法的性能比較
下面是3種代碼的寫法都是基于pandas
的,完成的功能也是一樣的。
2.1. 循環(huán)遍歷
給每條數(shù)據(jù)加一個(gè)評(píng)估的指標(biāo),最直接想到的方法就是遍歷所有的數(shù)據(jù),然后根據(jù)每條數(shù)據(jù)的情況,
給予一個(gè)評(píng)估指標(biāo)(優(yōu),中,差)。
首先,封裝一個(gè)評(píng)估一條數(shù)據(jù)的函數(shù):
def eval_stock(row):
"""
評(píng)估一條的數(shù)據(jù)
"""
# 成交額
volumn = row["收盤"] * row["成交量"]
if volumn > 1_000_000_000 and row["收盤"] > row["開盤"]:
return "優(yōu)"
if volumn < 100_000_000 and row["收盤"] < row["開盤"]:
return "差"
return "中"
然后用遍歷的方式評(píng)估我們準(zhǔn)備的數(shù)據(jù)(A股2024年1,2月份的日交易數(shù)據(jù))。
for idx, row in df.iterrows():
df.loc[idx, "評(píng)估"] = eval_stock(row)
df
雖然只有20多萬條數(shù)據(jù),但是執(zhí)行時(shí)間還挺長的,在jupyter notebook
中用 %%timeit
魔法函數(shù)測試性能如下。
%%timeit
for idx, row in df.iterrows():
df.loc[idx, "評(píng)估"] = eval_stock(row)
運(yùn)行結(jié)果:
36.4 s ± 367 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
執(zhí)行一次要36秒多,效率很低。
2.2. apply方法
apply
方法是pandas
提供的一種靈活處理數(shù)據(jù)的接口,它允許我們傳入一個(gè)自定義函數(shù)來處理數(shù)據(jù)。
下面我們看看這種方式的性能如何。
%%timeit
df["評(píng)估"] = df.apply(eval_stock, axis=1)
運(yùn)行結(jié)果:
4.9 s ± 86.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
性能提升非常明顯(36.4秒->4.9秒),代碼也變得更加簡潔。
2.3. 向量化方法
最后,我們看看終極的寫法,這種寫法把pandas
的數(shù)據(jù)結(jié)構(gòu)DataFrame
看成是一個(gè)一維的向量數(shù)組(每列一個(gè)向量),而不是一個(gè)二維的數(shù)值數(shù)組。
這樣,我們操作數(shù)據(jù)是以列為單位來操作,看看這樣寫的性能如何:
%%timeit
df["評(píng)估"] = "中"
df.loc[
(df["收盤"] * df["成交量"] > 1_000_000_000) & (df["收盤"] > df["開盤"]),
"評(píng)估",
] = "優(yōu)"
df.loc[
(df["收盤"] * df["成交量"] < 100_000_000) & (df["收盤"] < df["開盤"]), "評(píng)估"
] = "差"
運(yùn)行結(jié)果:
8.22 ms ± 434 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
運(yùn)行時(shí)間幾乎可以忽略不計(jì)。
3. 總結(jié)
同樣使用pandas
寫數(shù)據(jù)分析的代碼,性能差距居然會(huì)如此天差地別。文章來源:http://www.zghlxwxcb.cn/news/detail-841250.html
可見,學(xué)習(xí)pandas
,不僅僅是學(xué)習(xí)它的各種接口和函數(shù),
更重要的是了解從pandas
執(zhí)行的角度應(yīng)該如何看待數(shù)據(jù),是把數(shù)據(jù)看成一個(gè)一個(gè)獨(dú)立的值,還是一行一行或一列一列的向量。
只有這樣,才能用pandas
高效的處理數(shù)據(jù),這在數(shù)據(jù)量膨脹之后,會(huì)大大提高我們分析的效率。文章來源地址http://www.zghlxwxcb.cn/news/detail-841250.html
到了這里,關(guān)于Pandas:如何讓你的代碼性能飆升的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!