查找熊猫中时间序列数据中值的最后一个出现序列



我有 10 天的每分钟时间序列数据,有三列:time stampcategoryalarm。给定一个日期,我想groupby类别并找到在给定日期之前连续将闹钟设置为 1 的timestamps,并从此子集创建一个dataframe

'Category'       'Date'              'Alarm'
0      A        1999-11-10 12:01:00        1
1      A        1999-11-10 12:02:00        1
2      A        1999-11-10 12:03:00        1
3      A        1999-11-10 12:04:00        1
4      A        1999-11-10 12:05:00        0
5      A        1999-11-10 12:06:00        0
.
.
.
1101   A        1999-11-13 10:07:00        1
1102   A        1999-11-13 10:08:00        1
1103   A        1999-11-13 10:09:00        1
1104   B        1999-11-23 13:09:00        0
1105   B        1999-11-23 13:10:00        0
1106   B        1999-11-23 13:11:00        1
1107   B        1999-11-23 13:12:00        1
1108   B        1999-11-23 13:13:00        1
1109   B        1999-11-23 13:14:00        0
.
.
.
. 
2110   B        1999-11-26 13:13:00        0
2110   B        1999-11-26 13:14:00        0
2110   B        1999-11-26 13:15:00        1 
2111   B        1999-11-26 13:16:00        1 
2112   B        1999-11-26 13:17:00        1 
2113   B        1999-11-26 13:18:00        1 
2114   B        1999-11-26 13:19:00        1
2115   B        1999-11-26 13:20:00        0
2116   B        1999-11-26 13:21:00        0
2117   C        1999-12-02 17:11:00        1 
.
.    
.

我希望输出是一个只有这些行的新数据帧:

'Category'       'Date'              'Alarm'
1101   A        1999-11-13 10:07:00        1
1102   A        1999-11-13 10:08:00        1
1103   A        1999-11-13 10:09:00        1
2110   B        1999-11-23 13:15:00        1 
2111   B        1999-11-23 13:16:00        1 
2112   B        1999-11-23 13:17:00        1 
2113   B        1999-11-23 13:18:00        1 
2114   B        1999-11-23 13:19:00        1

即,每组中具有最后一个连续序列 1 的行处于警报状态。 我尝试过的:

df.groupby('category')['alarm'].apply(lambda x: x==1)

但这会使所有具有警报的行都为 1,而不仅仅是连续 1 的最后一个序列。任何关于如何获得此内容的说明将不胜感激。谢谢!:)

编辑 1:我刚刚提供了数据帧的子集。最后一个连续序列 1 可以出现在之前的任何天数(例如,如果时间序列是从 11 月 1 日到 11 月 10 日,对于一个类别,最后一个连续的 1 可能发生在 11 月 2 日或 11 月 8 日。而且 1 的长度也可以有所不同。

让我们试试

# convert to datetime type
df.Date = pd.to_datetime(df.Date)
# blocks of consecutive `1`:
s = (1-df.Alarm).cumsum()*df.Alarm
# last group of `1` within Category and day:
last_groups = s.groupby(df.Category).transform('max')
# output:
df[s==last_groups]

O输出:

Category                Date  Alarm
1101        A 1999-11-13 10:07:00      1
1102        A 1999-11-13 10:08:00      1
1103        A 1999-11-13 10:09:00      1
2110        B 1999-11-26 13:15:00      1
2111        B 1999-11-26 13:16:00      1
2112        B 1999-11-26 13:17:00      1
2113        B 1999-11-26 13:18:00      1
2114        B 1999-11-26 13:19:00      1
2117        C 1999-12-02 17:11:00      1
# Make date into datetime
df['Date'] = pd.to_datetime(df['Date'])
# Get rid of time part
df['Day'] = df['Date'].dt.strftime('%Y-%m-%d')
# Taking rolling sum of Alarms
k = df.groupby('Day')['Alarm'].rolling(3).sum().reset_index()
# Take last set of consecutive 3's per day
k = k[k['Alarm']==3].groupby('Day').last()
# Capture the index of each row in the original data frame
k = k['level_1'].values
# Drop day column
df.drop(columns=['Day'], inplace=True)
# Join the rows together
df = pd.concat([df.loc[x-2:].head(3) for x in k])

输出

Category                Date  Alarm
6         A 1999-11-10 12:07:00      1  
7         A 1999-11-10 12:08:00      1  
8         A 1999-11-10 12:09:00      1 
15        B 1999-11-23 13:15:00      1 
16        B 1999-11-23 13:16:00      1  
17        B 1999-11-23 13:17:00      1  

相关内容

最新更新