Python 熊猫-如果一行中满足条件,则向前面的行添加值,而不进行迭代
我对熊猫很陌生,面临着一个相当复杂的问题。由于我的解决方案使用了许多嵌套的迭代循环,我想知道是否有一种更快更“泛ASIC”的方法来实现这一点 我有一个类似于此简化版本的事件数据框架: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
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
到目前为止,我的解决方案是:
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