我想以矢量化方式编写以下代码,因为当前代码非常慢(并且想学习Python最佳实践)。基本上,代码说如果今天的价值在昨天价值的10%之内,那么今天的价值(在新栏目中)与昨天的价值相同。否则,今天的价值不变:
def test(df):
df['OldCol']=(100,115,101,100,99,70,72,75,78,80,110)
df['NewCol']=df['OldCol']
for i in range(1,len(df)-1):
if df['OldCol'][i]/df['OldCol'][i-1]>0.9 and df['OldCol'][i]/df['OldCol'][i-1]<1.1:
df['NewCol'][i]=df['NewCol'][i-1]
else:
df['NewCol'][i]=df['OldCol'][i]
return df['NewCol']
输出应如下:
OldCol NewCol
0 100 100
1 115 115
2 101 101
3 100 101
4 99 101
5 70 70
6 72 70
7 75 70
8 78 70
9 80 70
10 110 110
你能帮忙吗?
我想使用类似的东西,但我无法解决我的问题:
def test(df):
df['NewCol']=df['OldCol']
cond=np.where((df['OldCol'].shift(1)/df['OldCol']>0.9) & (df['OldCol'].shift(1)/df['OldCol']<1.1))
df['NewCol'][cond[0]]=df['NewCol'][cond[0]-1]
return df
答案 0 :(得分:2)
分三个步骤的解决方案:
df['variation']=(df.OldCol/df.OldCol.shift())
df['gap']=~df.variation.between(0.9,1.1)
df['NewCol']=df.OldCol.where(df.gap).fillna(method='ffill')
对于:
OldCol variation gap NewCol
0 100 nan True 100
1 115 1.15 True 115
2 101 0.88 True 101
3 100 0.99 False 101
4 99 0.99 False 101
5 70 0.71 True 70
6 72 1.03 False 70
7 75 1.04 False 70
8 78 1.04 False 70
9 80 1.03 False 70
10 110 1.38 True 110
它似乎比这个例子上的循环快30倍。
在一行中:
x=df.OldCol;df['NewCol']=x.where(~(x/x.shift()).between(0.9,1.1)).fillna(method='ffill')
答案 1 :(得分:0)
你应该布尔掩盖原始数据帧:
df[(0.9 <= df['NewCol']/df['OldCol']) & (df['NewCol']/df['OldCol'] <= 1.1)]
将为您提供NewCol
在OldCol
的10%范围内的所有行
所以要在这些行中设置NewCol
字段:
within_10 = df[(0.9 <= df['NewCol']/df['OldCol']) & (df['NewCol']/df['OldCol'] <= 1.1)]
within_10['NewCol'] = within_10['OldCol']
答案 2 :(得分:0)
由于你似乎在寻找自己的“跳跃”日子的好方法,我只会展示更棘手的一点。因此,假设您有一个长度为old
N
的numpy数组和相同大小的布尔numpy数组jump
。作为惯例,jump
的第0个元素设置为True
。然后你可以先计算跳跃之间的重复次数:
jump_indices = np.where(jumps)[0]
repeats = np.diff(np.r_[jump_indices, [N]])
一旦有了这些,您可以使用np.repeat
:
new = np.repeat(old[jump_indices], repeats)