Skip to main content
 首页 » 编程设计

python之Numpy:在引用前一行值时使用矢量化 for 循环

2025年05月04日19qq78292959

我有以下数据框,我想使用 numpy 创建一个名为“Value”的列以进行快速循环,同时引用同一列中的前一行值。

import pandas as pd 
import numpy as np 
 
df = pd.DataFrame( 
    { 
        "Product": ["A", "A", "A", "A", "B", "B", "B", "C", "C"], 
        "Inbound": [115, 220, 200, 402, 313, 434, 321, 343, 120], 
        "Outbound": [10, 20, 24, 52, 40, 12, 43, 23, 16], 
        "Is First?": ["Yes", "No", "No", "No", "Yes", "No", "No", "Yes", "No"], 
    } 
) 
  Product  Inbound  Outbound Is First?  Value 
0       A      115        10       Yes    125 
1       A      220        20        No    105 
2       A      200        24        No     81 
3       A      402        52        No     29 
4       B      313        40       Yes    353 
5       B      434        12        No    341 
6       B      321        43        No    298 
7       C      343        23       Yes    366 
8       C      120        16        No    350 

伪代码中Value列的公式为:

if ['Is First?'] = 'Yes' then [Value] = [Inbound] + [Outbound] 
else [Value] = [Previous Value] - [Outbound] 

现在创建 Value 列的理想方法是执行 for 循环 并使用 shift 来引用前一列(我不知何故无法工作)。但由于我将在一个巨大的数据集上应用它,我想对其使用 numpy 向量化方法。

for i in range(len(df)): 
    if df.loc[i, "Is First?"] == "Yes": 
        df.loc[i, "Value"] = df.loc[i, "Inbound"] + df.loc[i, "Outbound"] 
    else: 
        df.loc[i, "Value"] = df.loc[i, "Value"].shift(-1) + df.loc[i, "Outbound"] 

请您参考如下方法:

一种方式:
您可以将 np.subtract.accumulate 与 transform

一起使用
s = df['Is First?'].eq('Yes').cumsum() 
df['value'] = ((df.Inbound + df.Outbound).where(df['Is First?'].eq('Yes'), df.Outbound) 
                                         .groupby(s) 
                                         .transform(np.subtract.accumulate)) 
 
Out[1749]: 
  Product  Inbound  Outbound Is First?  value 
0       A      115        10       Yes    125 
1       A      220        20        No    105 
2       A      200        24        No     81 
3       A      402        52        No     29 
4       B      313        40       Yes    353 
5       B      434        12        No    341 
6       B      321        43        No    298 
7       C      343        23       Yes    366 
8       C      120        16        No    350 

另一种方式:
为 Yes 赋值。创建 groupid s 以用于 groupby。 Groupby 和 shift Outbound 计算 cumsum,并从每个组的"is"值中减去它。最后,用它来填充。

df['value'] = (df.Inbound + df.Outbound).where(df['Is First?'].eq('Yes')) 
s = df['Is First?'].eq('Yes').cumsum() 
s1 = df.value.ffill() - df.Outbound.shift(-1).groupby(s).cumsum().shift() 
df['value'] = df.value.fillna(s1) 
 
Out[1671]: 
  Product  Inbound  Outbound Is First?  value 
0       A      115        10       Yes  125.0 
1       A      220        20        No  105.0 
2       A      200        24        No   81.0 
3       A      402        52        No   29.0 
4       B      313        40       Yes  353.0 
5       B      434        12        No  341.0 
6       B      321        43        No  298.0 
7       C      343        23       Yes  366.0 
8       C      120        16        No  350.0