[英]Vectorizing an iterative function on Pandas DataFrame
我有一個 dataframe,其中第一行是初始條件。
df = pd.DataFrame({"Year": np.arange(4),
"Pop": [0.4] + [np.nan]* 3})
和 function f(x,r) = r*x*(1-x)
,其中r = 2
是常數, 0 <= x <= 1
。
我想通過逐行迭代地將 function 應用於Pop
列來生成以下 dataframe。 即df.Pop[i] = f(df.Pop[i-1], r=2)
df = pd.DataFrame({"Year": np.arange(4),
"Pop": [0.4, 0.48, 4992, 0.49999872]})
問題:是否有可能以矢量化的方式做到這一點?
我可以通過使用循環為 x 和 y 值構建列表來實現所需的結果,但這不是矢量化的。
我也試過這個,但所有nan
地方都充滿了0.48
。
df.loc[1:, "Pop"] = R * df.Pop[:-1] * (1 - df.Pop[:-1])
以矢量化方式執行此操作是不可能的。
根據定義,矢量化利用並行處理來減少執行時間。 但是您問題中的所需值必須按順序計算,而不是並行計算。 有關詳細說明,請參閱此答案。 像df.expanding(2).apply(f)和df.rolling(2).apply(f)這樣的東西是行不通的。
然而,獲得更高的效率是可能的。 您可以使用生成器進行迭代。 這是實現迭代過程的一個非常常見的結構。
def gen(x_init, n, R=2):
x = x_init
for _ in range(n):
x = R * x * (1-x)
yield x
# execute
df.loc[1:, "Pop"] = list(gen(df.at[0, "Pop"], len(df) - 1))
結果:
print(df)
Pop
0 0.400000
1 0.480000
2 0.499200
3 0.499999
小數據完全可以到此為止。 但是,如果 function 將執行很多次,您可以考慮使用numba優化生成器。
pip install numba
or conda 首先在控制台conda install numba
import numba
@numba.njit
。 將np.nan
的個數改為 10^6 ,自己查看執行時間的差異。 在我的 Core-i5 8250U 64 位筆記本電腦上實現了從 468 毫秒到 217 毫秒的改進。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.