python - 查找一天中事件的开始时间和结束时间 - Pandas 时间序列 - 这样结束时间不会落入第二天

标签 python pandas dataframe time-series python-datetime

我有一个气象时间序列 df:

df = pd.DataFrame({'date':['11/10/2017 0:00','11/10/2017 03:00','11/10/2017 06:00','11/10/2017 09:00','11/10/2017 12:00',
                       '11/11/2017 0:00','11/11/2017 03:00','11/11/2017 06:00','11/11/2017 09:00','11/11/2017 12:00',
                      '11/12/2017 00:00','11/12/2017 03:00','11/12/2017 06:00','11/12/2017 09:00','11/12/2017 12:00'],
              'value':[850,np.nan,np.nan,np.nan,np.nan,500,650,780,np.nan,800,350,690,780,np.nan,np.nan]})
df['date'] = pd.to_datetime(df.date.astype(str), format='%m/%d/%Y %H:%M',errors ='coerce') 
df.index = pd.DatetimeIndex(df.date)

通过这个数据框,我试图找出事件开始时间结束时间:

(df["value"] < 1000)

我使用了类似于 How to find the start time and end time of an event in python? 的解决方案 修改后的代码:

current_event = None
result = []
for event, time in zip((df["value"] < 1000), df.index):
    if event != current_event:
        if current_event is not None:
            result.append([current_event, start_time, time - pd.DateOffset(hours = 1, minutes = 30)])
        current_event, start_time = event, time - pd.DateOffset(hours = 1, minutes = 30)
df = pd.DataFrame(result, columns=['Event','StartTime','EndTime'])
df

输出为:

   Event           StartTime             EndTime
0   True 2017-11-09 22:30:00 2017-11-10 01:30:00
1  False 2017-11-10 01:30:00 2017-11-10 22:30:00
2   True 2017-11-10 22:30:00 2017-11-11 07:30:00
3  False 2017-11-11 07:30:00 2017-11-11 10:30:00
4   True 2017-11-11 10:30:00 2017-11-12 07:30:00

但是期望的输出是: enter image description here

所需的输出与上面的输出不同:

  1. 第二行(索引 1)中的结束时间2017-11-10 13:30:00

  2. 第五行(索引 4)的
  3. EndTime2017-11-11 13:30:00

  4. 新行第六行(索引 5)和第 6 行

逻辑:

  • 由于时间戳相隔 3 小时,因此假定事件在时间戳之前 1 小时 30 分钟开始,并在时间戳之后 1 小时 30 分钟结束。

  • 如果两个连续事件相似,则它们相加如下:第一个时间戳之前 1 小时 30 分钟,直到第二个时间戳之后 1 小时 30 分钟,依此类推。

  • 当天第一个事件的开始时间(即时间 00:00)应始终比 00:00 时间戳(即前一天的 22:30)早 1 小时 30 分钟。

  • 当天最后一个事件(即 12:00)的结束时间应始终比 12:00 时间戳(即当天的 13:30)晚 1 小时 30 分钟。

任何有关此问题的及时帮助将不胜感激。拼命尝试修复它,但还没有成功。

非常感谢!

最佳答案

创建输出数据框:

out = pd.DataFrame({"Event": df["value"] < 1000,
                    "StartTime": df["date"] - pd.DateOffset(hours=1, minutes=30),
                    "EndTime": df["date"] + pd.DateOffset(hours=1, minutes=30)},
                   index=df.index)
>>> out
    Event           StartTime             EndTime
0    True 2017-11-09 22:30:00 2017-11-10 01:30:00  # Group 0
1   False 2017-11-10 01:30:00 2017-11-10 04:30:00  # Group 1
2   False 2017-11-10 04:30:00 2017-11-10 07:30:00
3   False 2017-11-10 07:30:00 2017-11-10 10:30:00
4   False 2017-11-10 10:30:00 2017-11-10 13:30:00
5    True 2017-11-10 22:30:00 2017-11-11 01:30:00  # Group 2
6    True 2017-11-11 01:30:00 2017-11-11 04:30:00
7    True 2017-11-11 04:30:00 2017-11-11 07:30:00
8   False 2017-11-11 07:30:00 2017-11-11 10:30:00  # Group 3
9    True 2017-11-11 10:30:00 2017-11-11 13:30:00  # Group 4
10   True 2017-11-11 22:30:00 2017-11-12 01:30:00  # Group 5
11   True 2017-11-12 01:30:00 2017-11-12 04:30:00
12   True 2017-11-12 04:30:00 2017-11-12 07:30:00
13  False 2017-11-12 07:30:00 2017-11-12 10:30:00  # Group 6
14  False 2017-11-12 10:30:00 2017-11-12 13:30:00

定义一些辅助组:

event_group = out["Event"].ne(out["Event"].shift(fill_value=0)).cumsum()
time_group = (out["StartTime"] 
              - out["EndTime"].shift(fill_value=out["StartTime"].iloc[0])
              != pd.Timedelta(0)).cumsum()
>>> out[["Event"]].assign(EventGroup=event_group,
                          TimeGroup=time_group,
                          Groups=event_group + time_group)
    Event  EventGroup  TimeGroup  Groups
0    True           1          0       1  # Group 0
1   False           2          0       2  # Group 1
2   False           2          0       2
3   False           2          0       2
4   False           2          0       2
5    True           3          1       4  # Group 2
6    True           3          1       4
7    True           3          1       4
8   False           4          1       5  # Group 3
9    True           5          1       6  # Group 4
10   True           5          2       7  # Group 5
11   True           5          2       7
12   True           5          2       7
13  False           6          2       8  # Group 6
14  False           6          2       8

减少输出数据帧:

out = pd.DataFrame(out.groupby(event_group + time_group)
                      .apply(lambda g: (g["Event"].iloc[0],
                                        g["StartTime"].iloc[0], 
                                        g["EndTime"].iloc[-1]))
                      .tolist(), columns=["Event", "StartTime", "EndTime"])
>>> out
   Event           StartTime             EndTime
0   True 2017-11-09 22:30:00 2017-11-10 01:30:00
1  False 2017-11-10 01:30:00 2017-11-10 13:30:00
2   True 2017-11-10 22:30:00 2017-11-11 07:30:00
3  False 2017-11-11 07:30:00 2017-11-11 10:30:00
4   True 2017-11-11 10:30:00 2017-11-11 13:30:00
5   True 2017-11-11 22:30:00 2017-11-12 07:30:00
6  False 2017-11-12 07:30:00 2017-11-12 13:30:00

关于python - 查找一天中事件的开始时间和结束时间 - Pandas 时间序列 - 这样结束时间不会落入第二天,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67333038/

相关文章:

python - 使用来自不同数据帧的数据规范数据帧中的数据

r - 将列转换为日期类型会更改原始值的年份

python - 在 Pandas DataFrame 中选择多个列范围

dataframe - Julia 数据帧以纯格式写入 csv

python - 在 pandas 中条件很少的情况下如何选择列

python - CuPy 不适用于带有 CUDA 9.0 的 Ubuntu 18.04

python - 如何正确获取 pandas : loc[index, 列中的单个单元格] VS get_value(index,column)

python - 在 python 中将多个列表写入 JSON 文件

python - 如何使用 ctypes 在 Python 中模拟动态大小的 C 结构

Python DataFrame 未保存。如何永久分配呢?