Pandas 在相同 activity 但时间戳不同的情况下展平时间序列数据帧

Pandas flatten a time-series dataframe on same activity but different timestamps

我希望扁平化某些流程。基本上是查看彼此紧随其后的重复项。假设我有一个数据框:

d = {'time': [12-08-2020, 13-08-2020, 14-08-2020, 15-08-2020, 16-08-2020], 'state': [off, on, on, on, off]}
df = pd.DataFrame(data=d)

然后我将使用 time.shift() 创建“time_end”列。基本上是下排时间。结果:

         time state    time_end
0  12-08-2020   off  13-08-2020
1  13-08-2020    on  14-08-2020
2  14-08-2020    on  15-08-2020
3  15-08-2020    on  16-08-2020
4  16-08-2020   off         NaN

我现在的问题是,如何将它展平,使其实际上变成这样的 3 行:

         time state    time_end
0  12-08-2020   off  13-08-2020
1  13-08-2020    on  16-08-2020
4  16-08-2020   off         NaN

对于我的代码,如果它们后面跟着另一个 on,我不需要 repeat on。任何帮助将不胜感激。

我们可以根据当前行的 state 值不等于下一行的 state 值的位置来过滤 DataFrame,然后通过向后移回过滤后的 time_end 列来创建 time_end 列=15=] 列:

import pandas as pd

df = pd.DataFrame(data={
    'time': ['12-08-2020', '13-08-2020', '14-08-2020', '15-08-2020',
             '16-08-2020'],
    'state': ['off', 'on', 'on', 'on', 'off']
})

new_df = df[df['state'].ne(df['state'].shift())].reset_index(drop=True)
new_df['time_end'] = new_df['time'].shift(-1)

new_df:

         time state    time_end
0  12-08-2020   off  13-08-2020
1  13-08-2020    on  16-08-2020
2  16-08-2020   off         NaN

我们可以通过.shift() + .ne() + .cumsum()得到连续相同state的分组。

然后,对于每个组(连续相同的 state),我们使用 .groupby() + .agg() 获得 time 的第一个条目和 time_end 的最后一个条目,如下所示:

df['state_group'] = df['state'].ne(df['state'].shift()).cumsum()

df_out = df.groupby('state_group').agg({'time': 'first', 'state': 'first', 'time_end': 'last'}).reset_index(drop=True)

结果:

print(df_out)

         time state    time_end
0  12-08-2020   off  13-08-2020
1  13-08-2020    on  16-08-2020
2  16-08-2020   off        None

仅供参考,以下临时数据帧是在上述第一行代码之后使用连续相同 state 的分组创建的。我们基于这个分组来聚合想要的扁平化结果。

         time state    time_end  state_group
0  12-08-2020   off  13-08-2020            1
1  13-08-2020    on  14-08-2020            2
2  14-08-2020    on  15-08-2020            2
3  15-08-2020    on  16-08-2020            2
4  16-08-2020   off         NaN            3