在 pandas 或 numpy 中,我们可以在行上设置一个标志来进行矢量化并将其用于下一行计算吗
In pandas or numpy can we set a flag on row to do vectorization and use it for next row calculations
我是 python 的新手,但已经进入编程世界一段时间了。我已经尝试使用 python 数据帧和 iloc
通过 if else 循环执行以下操作并成功。我想使用矢量化。问题是,一旦数据根据 规则 1 (b < a) 更改其状态,我希望它在 规则 2 (c < a) 适用。
因此输入和输出将如下所示:
我已经尝试过 numpy select 和 numpy where with shift 但是比较发生在同一列上所以我无法让它工作。当规则 2 不适用时,它第一次起作用。因为上面是我从我的问题中创建的示例问题,所以很难提供代码
Flag 是我所期望的,但我不明白
df 带有循环而 df1 带有 numpy - 我无法让它看起来一样
import pandas as pd
import numpy as np
df = pd.DataFrame({"a": [20,25,30,32,25,26,30,24,25,30,30,35,20,22,25,28,29,31,25,21], "b": [26,28,26,35,34,34,31,26,28,29,31,32,18,24,30,35,32,35,36,30], "c":[18,19,20,22,23,24,34,22,23,31,32,38,22,21,22,21,18,22,28,31]})
df1 = df
position=''
Flag = False
df = df.assign(flag=Flag)
for id1, id2 in zip(df.iterrows(), df.iloc[1:].iterrows()):
if id1[1]['b'] < id1[1]['a'] :
Flag=True
position='rule1True'
elif ( id1[1]['c'] < id1[1]['a'] and (position =='rule1True' or position == 'rule2True') ):
Flag = True
position = 'rule2True'
else :
Flag = False
position = ''
df.at[id1[0],'flag'] = Flag
print(df)
df1['rule1'] = np.select([df1['b'] < df1['a']],[True], default= False)
df1['rule2'] = np.select([( df1['rule1'].shift(1) & (df1['c'] < df1['a']))],[True], default= False)
df1['flag'] = np.select([( df1['rule1'] | df1['rule2'])],[True], default= False)
print(df1)
我的 for 循环解决方案非常慢。这是一个适当的矢量解决方案,这有效。非常快。
mask1 = df['b'] < df['a']
mask2 = df['c'] < df['a']
mask3 = (mask1 == False) & (mask2 == False)
这个 True/False 标志在 mask1 mask3 交替时改变。
df.loc[mask1,'flag'] = True
df.loc[mask3,'flag'] = False
使用正向填充来填充 NaN。
df['flag'].ffill(inplace=True)
前几行可能是Nan,它们是假的。填写 False
df['flag'] = df['flag'].fillna(False)
在一百万行上测试:
CPU times: user 917 ms, sys: 7.99 ms, total: 925 ms
示例输出:
a b c flag
0 22 21 37 True
1 21 31 30 False
2 25 23 32 True
3 34 36 22 True
4 31 36 30 True
5 20 32 36 False
6 25 24 24 True
7 24 20 29 True
8 36 36 22 True
9 36 24 25 True
10 22 24 20 True
11 22 24 27 False
12 31 37 26 False
13 37 24 22 True
14 28 22 26 True
15 27 27 32 False
16 26 32 36 False
17 32 37 30 False
18 28 37 36 False
19 37 22 24 True
完整代码:
df = pd.DataFrame(np.random.randint(20, 38, [1000000,3]), columns=['a', 'b', 'c'])
mask1 = df['b'] < df['a']
mask2 = df['c'] < df['a']
mask3 = (mask1 == False) & (mask2 == False)
df.loc[mask1,'flag'] = True
df.loc[mask3,'flag'] = False
df['flag'].ffill(inplace=True)
df['flag'] = df['flag'].fillna(False)
我是 python 的新手,但已经进入编程世界一段时间了。我已经尝试使用 python 数据帧和 iloc
通过 if else 循环执行以下操作并成功。我想使用矢量化。问题是,一旦数据根据 规则 1 (b < a) 更改其状态,我希望它在 规则 2 (c < a) 适用。
因此输入和输出将如下所示:
我已经尝试过 numpy select 和 numpy where with shift 但是比较发生在同一列上所以我无法让它工作。当规则 2 不适用时,它第一次起作用。因为上面是我从我的问题中创建的示例问题,所以很难提供代码
Flag 是我所期望的,但我不明白
df 带有循环而 df1 带有 numpy - 我无法让它看起来一样
import pandas as pd
import numpy as np
df = pd.DataFrame({"a": [20,25,30,32,25,26,30,24,25,30,30,35,20,22,25,28,29,31,25,21], "b": [26,28,26,35,34,34,31,26,28,29,31,32,18,24,30,35,32,35,36,30], "c":[18,19,20,22,23,24,34,22,23,31,32,38,22,21,22,21,18,22,28,31]})
df1 = df
position=''
Flag = False
df = df.assign(flag=Flag)
for id1, id2 in zip(df.iterrows(), df.iloc[1:].iterrows()):
if id1[1]['b'] < id1[1]['a'] :
Flag=True
position='rule1True'
elif ( id1[1]['c'] < id1[1]['a'] and (position =='rule1True' or position == 'rule2True') ):
Flag = True
position = 'rule2True'
else :
Flag = False
position = ''
df.at[id1[0],'flag'] = Flag
print(df)
df1['rule1'] = np.select([df1['b'] < df1['a']],[True], default= False)
df1['rule2'] = np.select([( df1['rule1'].shift(1) & (df1['c'] < df1['a']))],[True], default= False)
df1['flag'] = np.select([( df1['rule1'] | df1['rule2'])],[True], default= False)
print(df1)
我的 for 循环解决方案非常慢。这是一个适当的矢量解决方案,这有效。非常快。
mask1 = df['b'] < df['a']
mask2 = df['c'] < df['a']
mask3 = (mask1 == False) & (mask2 == False)
这个 True/False 标志在 mask1 mask3 交替时改变。
df.loc[mask1,'flag'] = True
df.loc[mask3,'flag'] = False
使用正向填充来填充 NaN。
df['flag'].ffill(inplace=True)
前几行可能是Nan,它们是假的。填写 False
df['flag'] = df['flag'].fillna(False)
在一百万行上测试:
CPU times: user 917 ms, sys: 7.99 ms, total: 925 ms
示例输出:
a b c flag
0 22 21 37 True
1 21 31 30 False
2 25 23 32 True
3 34 36 22 True
4 31 36 30 True
5 20 32 36 False
6 25 24 24 True
7 24 20 29 True
8 36 36 22 True
9 36 24 25 True
10 22 24 20 True
11 22 24 27 False
12 31 37 26 False
13 37 24 22 True
14 28 22 26 True
15 27 27 32 False
16 26 32 36 False
17 32 37 30 False
18 28 37 36 False
19 37 22 24 True
完整代码:
df = pd.DataFrame(np.random.randint(20, 38, [1000000,3]), columns=['a', 'b', 'c'])
mask1 = df['b'] < df['a']
mask2 = df['c'] < df['a']
mask3 = (mask1 == False) & (mask2 == False)
df.loc[mask1,'flag'] = True
df.loc[mask3,'flag'] = False
df['flag'].ffill(inplace=True)
df['flag'] = df['flag'].fillna(False)