如果条件扩展操作

时间:2019-09-26 16:14:46

标签: python pandas dataframe

假设我有以下数据框。

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的时间的最后一行,以便可以从中减去最近一行的时间。我不确定该怎么做。

由于expanding()。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))

任何其他想法或代码都可以帮助我。谢谢。

1 个答案:

答案 0 :(得分:0)

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

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