我有 10 天的每分钟时间序列数据,有三列:time stamp
、category
、alarm
。给定一个日期,我想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