首页 > 解决方案 > 使用 if 条件扩展操作

问题描述

假设我有以下数据框。

df = pd.DataFrame([[1234,0,1],[1234,1,2],[1234,0,3],[2256,1,4],[1234,0,5],[1234,1,6],[1234,0,7],[2256,0,8],[2256,1,9],[2256,0,10]],columns=['ID','result','time'])

例子

     ID  result  time
0  1234       0     1
1  1234       1     2
2  1234       0     3
3  2256       1     4
4  1234       0     5
5  1234       1     6
6  1234       0     7
7  2256       0     8
8  2256       1     9
9  2256       0     10
10 1234       1     11

我想按 ID 分组。然后,我想为每个 ID 添加列“time_since_1”。'time_since_1' 是自每个 ID 的结果变为 1 以来的持续时间。每个 ID 的结果变为 1时间将重置。所以我也需要移位。

期望的输出

     ID  result  time time_since_1
0  1234       0     1            0  → Nothing hasn't happened yet
1  1234       1     2            0  → first time = 0 (ID = 1234)
2  1234       0     3            1  → 3-2 = 1        (ID = 1234)
3  2256       1     4            0  → first time = 0 (ID = 2256)
4  1234       0     5            3  → 5-2 = 3        (ID = 1234)
5  1234       1     6            4  → 6-2 = 4        (ID = 1234)  
6  1234       0     7            1  → 7-6 = 1        (ID = 1234)
7  2256       0     8            4  → 8-4 = 4        (ID = 2256) 
8  2256       1     9            5  → 9-4 = 5        (ID = 2256) 
9  2256       0     10           1  → 10-9 = 1       (ID = 2256)
10 1234       1     11           5  → 11-6 = 5       (ID = 1234) 

我尝试编写代码,最终我发现 .expanding() 在这种情况下可能会有所帮助。所以,我尝试了下面的代码。

df['time_since_1'] = df.groupby('ID').apply(lambda x: x.expanding().apply(lambda y: y['time'] - y[y['result']==1].tail(1)['time']))

这种事情不起作用,因为 .expanding().apply() 返回 ndarray,并且不知道如何处理这些。我需要使用expanding() 并获取result=1 的最后一行时间,这样我就可以从中减去最近行的时间。我不知道该怎么做。

由于 expand().apply() 返回 ndarray 我试图从中制作数据框,但似乎也有错误,并且不确定正确的方法。

def func(y):
    df = pd.DataFrame(y,columns=['ID','result','time_since_1'])
    # filter here
    # return one value (time_since_1)

df['time_since_1'] = df.groupby('ID').apply(lambda x: x.expanding().apply(lambda y: func(y))

任何不同的想法或代码都可以帮助我。谢谢你。

标签: pythonpandasdataframe

解决方案


我的尝试不是预期的解决方案,但也许可以帮助你......

r=df.groupby('ID').apply(lambda x: x.where(x['result'].eq(1))['time'].shift().ffill().fillna(df['time']))
df['time_since_1']=df['time']-r.reset_index().sort_values('level_1').set_index('level_1')['time']
print(df)
      ID  result  time  time_since_1
0   1234       0     1           0.0
1   1234       1     2           0.0
2   1234       0     3           1.0
3   2256       1     4           0.0
4   1234       0     5           3.0
5   1234       1     6           4.0
6   1234       0     7           1.0
7   2256       0     8           4.0
8   2256       1     9           5.0
9   2256       0    10           1.0
10  1234       1    11           5.0

推荐阅读