向量化在 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
我有一个包含 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