Python 熊猫-如果一行中满足条件,则向前面的行添加值,而不进行迭代

Python 熊猫-如果一行中满足条件,则向前面的行添加值,而不进行迭代,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,我对熊猫很陌生,面临着一个相当复杂的问题。由于我的解决方案使用了许多嵌套的迭代循环,我想知道是否有一种更快更“泛ASIC”的方法来实现这一点 我有一个类似于此简化版本的事件数据框架: min sec isDone sessionId 2 40 False 1 2 50 False 1 2 55 False 1 2 58 False 1 3 01 False 1

我对熊猫很陌生,面临着一个相当复杂的问题。由于我的解决方案使用了许多嵌套的迭代循环,我想知道是否有一种更快更“泛ASIC”的方法来实现这一点

我有一个类似于此简化版本的事件数据框架:

min  sec  isDone       sessionId
2    40   False        1
2    50   False        1
2    55   False        1
2    58   False        1
3    01   False        1
3    12   True         1
5    0    False        1
5    5    False        1
5    15   False        1
5    30   True         1
5    50   False        1
2    0    False        2
2    10   False        2
2    30   False        2
2    50   True         2
现在,我想添加一个列,其中包含“isDone”中下一个“True”之前的秒数(最长为一定数量的秒数),但仅在同一个“sessionId”中。所有其他价值观都将保持不变

在20秒钟内,这将如下所示:

min  sec  isDone       sessionId  secToDone
2    40   False        1          NaN
2    50   False        1          NaN
2    55   False        1          17
2    58   False        1          14
3    01   False        1          11
3    12   True         1          0
5    0    False        1          NaN
5    5    False        1          NaN
5    15   False        1          15
5    30   True         1          0
5    50   False        1          NaN
2    0    False        2          NaN
2    10   False        2          NaN
2    30   False        2          20
2    50   True         2          0
到目前为止,我的解决方案是:

  • 迭代sessionid并选择行
  • 仅使用此选择中的“True”值构建第二个数据帧df_
  • 迭代此df_done-Dataframe,并在“秒”内选择前面的行
  • 迭代上述行并写入值
  • 以下是我到目前为止的代码(sessionId上的迭代缺失,因为我目前只测试了一个会话):

    def get_前置(df_数据集,秒=20):
    df_done=df_数据集[(df_数据集['isDone']==True]
    对于df_done.itertuples()中的行:
    done_min=getattr(第行,“分钟”)
    done_sec=getattr(第二行)
    如果完成_秒<秒:
    pre_min=完成_min-1
    预备秒=60+完成秒-秒
    其他:
    pre_min=完成_min
    预秒=完成秒-秒
    
    对于df_dataset.loc[(pre_min==df_dataset['minute'])和(pre_sec中的r,首先,您需要将分和秒组合成合理的值:

    df['t'] = df['min'] * 60 + df.sec
    
        min  sec  isDone  sessionId    t
    0     2   40   False          1  160
    1     2   50   False          1  170
    2     2   55   False          1  175
    3     2   58   False          1  178
    
    然后,您要标记发生
    True
    的所有时间:

    df['true_t'] = df[df.isDone].t
    
        min  sec  isDone  sessionId    t  true_t
    0     2   40   False          1  160     NaN
    1     2   50   False          1  170     NaN
    2     2   55   False          1  175     NaN
    3     2   58   False          1  178     NaN
    4     3    1   False          1  181     NaN
    5     3   12    True          1  192   192.0
    6     5    0   False          1  300     NaN
    
    现在,groupby的魔力在于:

    df['next_true_t'] = df.groupby('sessionId').true_t.bfill()
    
        min  sec  isDone  sessionId    t  true_t  next_true_t
    0     2   40   False          1  160     NaN        192.0
    1     2   50   False          1  170     NaN        192.0
    2     2   55   False          1  175     NaN        192.0
    3     2   58   False          1  178     NaN        192.0
    4     3    1   False          1  181     NaN        192.0
    5     3   12    True          1  192   192.0        192.0
    6     5    0   False          1  300     NaN        330.0
    7     5    5   False          1  305     NaN        330.0
    8     5   15   False          1  315     NaN        330.0
    9     5   30    True          1  330   330.0        330.0
    10    5   50   False          1  350     NaN          NaN
    11    2    0   False          2  120     NaN        170.0
    12    2   10   False          2  130     NaN        170.0
    13    2   30   False          2  150     NaN        170.0
    14    2   50    True          2  170   170.0        170.0
    
    现在,计算您的差异非常简单:

    df['diff'] = df.next_true_t - df.t
    
        min  sec  isDone  sessionId    t  true_t  next_true_t  diff
    0     2   40   False          1  160     NaN        192.0  32.0
    1     2   50   False          1  170     NaN        192.0  22.0
    2     2   55   False          1  175     NaN        192.0  17.0
    3     2   58   False          1  178     NaN        192.0  14.0
    4     3    1   False          1  181     NaN        192.0  11.0
    5     3   12    True          1  192   192.0        192.0   0.0
    6     5    0   False          1  300     NaN        330.0  30.0
    7     5    5   False          1  305     NaN        330.0  25.0
    8     5   15   False          1  315     NaN        330.0  15.0
    9     5   30    True          1  330   330.0        330.0   0.0
    10    5   50   False          1  350     NaN          NaN   NaN
    11    2    0   False          2  120     NaN        170.0  50.0
    12    2   10   False          2  130     NaN        170.0  40.0
    13    2   30   False          2  150     NaN        170.0  20.0
    14    2   50    True          2  170   170.0        170.0   0.0
    

    我将让您自行决定如何根据秒数忽略值,但这非常简单。

    哇,感谢您的广泛帮助,将其应用于我的项目应该很容易。一个小问题:为什么不在现有列“true\t”上执行groupby/bfill?哦,您是说覆盖现有的co列?是的,这很好,但您仍然希望按会话id进行分组。不过,我会将列命名为不同的名称(即,
    next\u true\t
    )。它更多地是为了一步一步地显示正在发生的事情。
    df['diff'] = df.next_true_t - df.t
    
        min  sec  isDone  sessionId    t  true_t  next_true_t  diff
    0     2   40   False          1  160     NaN        192.0  32.0
    1     2   50   False          1  170     NaN        192.0  22.0
    2     2   55   False          1  175     NaN        192.0  17.0
    3     2   58   False          1  178     NaN        192.0  14.0
    4     3    1   False          1  181     NaN        192.0  11.0
    5     3   12    True          1  192   192.0        192.0   0.0
    6     5    0   False          1  300     NaN        330.0  30.0
    7     5    5   False          1  305     NaN        330.0  25.0
    8     5   15   False          1  315     NaN        330.0  15.0
    9     5   30    True          1  330   330.0        330.0   0.0
    10    5   50   False          1  350     NaN          NaN   NaN
    11    2    0   False          2  120     NaN        170.0  50.0
    12    2   10   False          2  130     NaN        170.0  40.0
    13    2   30   False          2  150     NaN        170.0  20.0
    14    2   50    True          2  170   170.0        170.0   0.0