我有一个事件的df。基本示例可以通过代码重现:
data = [['2019-01-11 16:27:39', 'AC', '2019-01-11 16:54:53'], ['2019-01-11 16:27:39', 'DC', '2019-01-11 16:54:53'], ['2019-01-11 17:03:42', 'AC', '2019-01-14 10:00:25'], ['2019-01-11 17:03:42', 'DC', '2019-01-14 09:58:39'], ['2019-01-11 17:03:42', 'Battery', '2019-01-14 10:00:48'], ['2019-01-11 17:03:48', 'Cell', '2019-01-12 17:26:48'], ['2019-01-14 10:00:36', 'DC', '2019-01-14 10:33:42'], ['2019-01-14 10:32:42', 'AC', '2019-01-14 10:45:27']]
df = pd.DataFrame(data, columns = ['Start', 'Alarm', 'End'])
df['Start'] = pd.to_datetime(df['Start'], format='%d.%m.%Y %H:%M:%S')
df['End'] = pd.to_datetime(df['End'], format='%d.%m.%Y %H:%M:%S')
我的总体目标是监控发生的警报。诸如直流/电池/电池之类的报警通常与交流电源同时或稍后发生。
因此,我想添加“AC Start”列,该列将填充与其他告警相关联的对应AC告警的时间戳,然后计算AC告警发生与其他告警发生之间的时间差。
下面是我的代码:
ac_mask = df.Alarm.eq('AC')
df['AC Start'] = df.Start.where(ac_mask).ffill().mask(ac_mask)
df['AC End'] = df.End.where(ac_mask).ffill().mask(ac_mask)
df['Time between events'] = (df['Start'] - df['AC Start']).dt.total_seconds()/60
它工作得很好,直到我面临警报比正确的AC更早发生,并与错误关联的情况。(见图)
所以我的问题是,我如何调整代码,使其只在一天内工作,以查找匹配项?
发布于 2019-12-03 22:51:26
只需对您的ac_mask
进行一些额外的过滤,并稍微更改一下创建AC Start
和AC End
的方式:
# 1. Change condition to ne('AC') instead of eq('AC')
# 2. Add conditional that Start must be on the same date, backfilled NA values
ac_mask = df.Alarm.ne('AC') & df.Start.dt.date.eq(df.Start.shift().bfill().dt.date)
让我们看看现在的面具是什么样子的:
>>> df['ac_mask'] = ac_mask
>>> df[['Start', 'Alarm', 'ac_mask']]
Start Alarm ac_mask
0 2019-01-11 16:27:39 AC False
1 2019-01-11 16:27:39 DC True
2 2019-01-11 17:03:42 AC False
3 2019-01-11 17:03:42 DC True
4 2019-01-11 17:03:42 Battery True
5 2019-01-11 17:03:48 Cell True
6 2019-01-14 10:00:36 DC False # <-- Alarm on different date is no longer captured
7 2019-01-14 10:32:42 AC False
现在还要调整掩码AC Start
和AC End
的方式
df['AC Start'] = df.Start.mask(ac_mask).ffill().where(ac_mask)
df['AC End'] = df.End.mask(ac_mask).ffill().where(ac_mask)
其余的都是一样的:
df['Time between events'] = (df['Start'] - df['AC Start']).dt.total_seconds()/60
>>> df
Start Alarm End AC Start AC End Time between events
0 2019-01-11 16:27:39 AC 2019-01-11 16:54:53 NaT NaT NaN
1 2019-01-11 16:27:39 DC 2019-01-11 16:54:53 2019-01-11 16:27:39 2019-01-11 16:54:53 0.0
2 2019-01-11 17:03:42 AC 2019-01-14 10:00:25 NaT NaT NaN
3 2019-01-11 17:03:42 DC 2019-01-14 09:58:39 2019-01-11 17:03:42 2019-01-14 10:00:25 0.0
4 2019-01-11 17:03:42 Battery 2019-01-14 10:00:48 2019-01-11 17:03:42 2019-01-14 10:00:25 0.0
5 2019-01-11 17:03:48 Cell 2019-01-12 17:26:48 2019-01-11 17:03:42 2019-01-14 10:00:25 6.0
6 2019-01-14 10:00:36 DC 2019-01-14 10:33:42 NaT NaT NaN
7 2019-01-14 10:32:42 AC 2019-01-14 10:45:27 NaT NaT NaN
发布于 2019-12-03 22:15:20
用循环解决了这个问题,但肯定有更好的方法。因此,这个问题仍然悬而未决。
as_start = tr[tr['Alarm']=='AC']['Start'].dt.date.unique()
dt = pd.DataFrame([])
for date in as_start:
tt = tr[tr['Start'].dt.date==date]
ac_mask = tt.Alarm.eq('AC')
tt['AC Start'] = tt.Start.where(ac_mask).ffill().mask(ac_mask)
tt['AC End'] = tt.End.where(ac_mask).ffill().mask(ac_mask)
tt['Time between events'] = (tt['Start'] - tt['AC Start']).dt.total_seconds()/60
dt = dt.append(tt)
https://stackoverflow.com/questions/59157967
复制相似问题