向量化在 Pandas 中具有条件的顺序操作

vectorizing a sequential operation that has a conditional in Pandas

我有一个包含 3 列的 Pandas 数据框。有一系列布尔值、一系列值和一列我要填充 C。我也有 C 的初始值。

A         B         C
----------------------
True     10        100
False    20        NaN
True     25        NaN
True     28        NaN
...

我希望 C 列(对于 C[1:])的值遵循以下规则。

if A[i - 1]:
    C[i] = C[i - 1] * B[i] / B[i - 1]
else:
    C[i] = C[i - 1]

当然这个公式不能确定C[0],但是提供了C[0]

有没有一种方法可以使用矢量化操作高效地完成此操作?

我试过的:

以下命令不考虑操作的顺序性质。

df.loc[df.A , 'C'] = df.C.shift(1) * df.B / df.B.shift(1)
df.loc[df.A == 0, 'C'] = df.C.shift(1)

如果我确实要使用应用函数来计算它,我可能必须像下面这样制作新的移位列,然后只 运行 申请行 [1:]?但是如何获取 C 的更新前值?

df["s_A"] = df.A.shift(1)
df["s_B"] = df.B.shift(1)
df["s_C"] = df.C.shift(1)
df["s_A"][0] = False; # this assumption is okay within the purposes 

这应该行得通吗?有没有更快的方法?多个数据帧总共可能有多达 400,000 行,但它对时间不是特别敏感。

为了清楚起见,我会提到总共大约有 12 列,但只有这三列与此操作相关。

是否可以向量化此操作?还有其他方法可以解决吗?

谢谢。

我认为向量化递归代数很难。

一般的方法是递归

A = df['A'].to_numpy()
B = df['B'].to_numpy()
C = df['C'].to_numpy()

for i in np.arange(1, len(A)):
    C[i] = C[i-1] if not A[i-1] else C[i-1] * B[i] / B[i-1]

df['A'] = A
df['B'] = B
df['C'] = C

或者,分析你的案例后,可以算出一个累积乘积问题,可以通过以下方式解决:

df['C'] = df['C'].fillna(
    df['A'].shift(1) * df['B'] / df['B'].shift(1) +\
    (1 - df['A'].shift(1))
).cumprod()

两种方式都会产生相同的结果。

       A   B      C
0   True  10  100.0
1  False  20  200.0
2   True  25  200.0
3   True  28  224.0