给定一个具有三列 (C1,C2,C3) 和一系列等长正数 (coeff) 的 pandas 数据帧,我正在计算第四列 C4,如下所示
def event(data, coeff, rate_low=2, rate_high=2):
bot_col_name = 'C4'
data[bot_col_name] = -1
I = data.index
for k in range(len(I)-1):
i = I[k]
next_val = data.at[ I[k+1], 'C1']
c = coeff.at[i]
low_bound = next_val - rate_low*c
high_bound = next_val + rate_high*c
for j in range(k+1, len(data)):
if data.at[ I[j], 'C2'] < low_bound:
data.at[i, bot_col_name] = 0
break
if data.at[ I[j], 'C3'] >= high_bound:
data.at[i, bot_col_name] = 1
break
return data
换句话说,给定一行,我们计算某个上限和下限,然后根据我们首先达到 C2 下的上限还是 C3 上的下限来设置相应的行元素。
作为一个例子,考虑熊猫表 D
C1 C2 C3
0 2 5 5
1 10 12 2
2 8 3 17
3 30 25 3
现在如果 coeff = [3,3,5,7] 那么在计算第一行的值时,low_bound 为 10-2*3=4,high_bound 为 10+2*3=16。我们现在必须找到最小索引 i>0 使得 D.loc[i, 'C2'] < 4 或 D.loc[i,'C3'] >= 16。我们看到第一个这样的 i 是 1 并且因为这恰好满足第一个条件,所以我们将这一行的新列设置为 0。
不幸的是,上述解决方案效率很低。我已经尝试通过向后计算值并尝试缓存结果来优化它(有时可以从“过去”值推断出 C4 的值),但不幸的是它并没有明显更好。
根据我的经验,获得最大性能的最佳方法是尝试在 pandas 框架内尽可能多地表达。
是否有任何有意义的方式可以优化上述代码?
编辑。使用已接受答案的代码并替换以下函数可获得最佳结果。
@njit
def get_c4(low_bound, high_bound, c2, c3):
r1 = np.argwhere( c2 < low_bound )
r2 = np.argwhere( c3 >= high_bound )
if len(r1) == 0 and len(r2) == 0:
return -1
elif len(r1) == 0:
return 1
elif len(r2) == 0:
return 0
return int (r1[0] > r2[0])
人到中年有点甜
Helenr
相关分类