我有一个大约600万行的数据框,我需要重复分析进行模拟。以下是数据的非常简单的表示。
适用于action=1
,
我想要设计一种有效的方法来实现这个目标
For index,row in df.iterrows():
`Result = the first next row where (price2 is >= row.price1 +4) and index > row.index`
或者如果不存在
return index+100
(即活动超时)。
import pandas as pd
df = pd.DataFrame({'Action(y/n)' : [0,1,0,0,1,0,1,0,0,0], 'Price1' : [1,8,3,1,7,3,8,2,3,1], 'Price2' : [2,1,1,5,3,1,2,11,12,1]})
print(df)
Action(y/n) Price1 Price2
0 0 1 2
1 1 8 1
2 0 3 1
3 0 1 5
4 1 7 3
5 0 3 1
6 1 8 2
7 0 2 11
8 0 3 12
9 0 1 1
导致类似这样的事情:
Action(y/n) Price1 Price2 ExitRow(IndexOfRowWhereCriteriaMet)
0 0 14 2 9
1 1 8 1 8
2 0 3 1 102
3 0 1 5 103
4 1 7 3 7
5 0 3 1 105
6 1 8 2 8
7 0 2 11 107
8 0 3 12 108
9 0 1 1 109
我尝试了一些方法,这些方法都非常慢。 这个最好的一个映射它,但真的不够快。
df['ExitRow'] = list(map(ATestFcn, df.index,df.price1))
def ATestFcn(dfIx, dfPrice1):
ExitRow = df[((df.price2>(price1+4))&(df.index >dfIx)& (df.index<=dfIx+TimeOut))].index.min()
if pd.isnull(ExitRow):
return dfIx+ TimeOut
else:
return ExitRow
我还用循环测试了这个,它慢了大约25% - 但这是明智的想法 基本相同。
我认为必须有一个更聪明或更快的方法来做到这一点,一个掩码可能是有用的,除非你不能填写这些数据,因为price2
一行可能是在另一行price2
之后的数千行,我无法找到一种方法将合并转换为交叉应用,就像在TSQL中那样。
答案 0 :(得分:0)
要查找符合条件的第一行索引,可以使用
cur_row_idx = 100 # we want the row after 100
next_row_idx = (df[cur_row_idx:].Price2 >= df[cur_row_idx:].Price1 + 4).argmax()
然后,你想设置一个截止值,比如说,你得到的最大值是TimeOut
- 所以它可能是
next_row_idx = np.min(((df[cur_row_idx:].Price2 >= df[cur_row_idx:].Price1 + 4).argmax() , dfIx + TimeOut))
我没有检查大型数据集的性能,但希望它有所帮助。 如果您愿意,您也可以将其包装成一个函数:
def ATestFcn(dfIx, df, TimeOut):
return np.min(((df[dfIx:].Price2 >= df[dfIx:].Price1 + 4).argmax() , dfIx + TimeOut))
修改:刚刚测试过,速度非常快,请看下面的结果:
df = pd.DataFrame()
Price1 = np.random.randint(100, size=10e6)
Price2 = np.random.randint(100, size=10e6)
df["Price1"] = Price1
df["Price2"] = Price2
timeit ATestFcn(np.random.randint(1e6), df, 100)
Out[62]: 1 loops, best of 3: 289 ms per loop