下一行匹配标准 - python pandas数据帧

时间:2015-10-21 08:45:31

标签: python pandas

我有一个大约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中那样。

1 个答案:

答案 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