由于某些奇怪的原因,我无法立即转换您的日期,但需要替换空格。尽管如此,让我们先将您的 Date 列转换为 pandas 日期并将其设置为索引:
>>> df['Start Date'] = pd.to_datetime(df['Start Date'].str.replace(r'\s+', ' ', regex=True))
>>> df = df.set_index('Start Date')
>>> df
Event Duration
2021-01-01 00:00:00 2 540
2021-01-01 09:00:00 1 180
2021-01-01 12:00:00 2 20
2021-01-01 12:20:00 1 1440
2021-01-02 12:20:00 2 60
2021-01-02 13:20:00 1 20
然后我们可以计算需要进行哪些拆分,即日期发生变化但未显示为 Start Date 的时间戳,并将其添加到索引中:
>>> splits = pd.date_range(df.index.min().floor(freq='D') + pd.Timedelta(days=1), df.index.max().ceil(freq='D') - pd.Timedelta(days=1), freq='D')
>>> df = df.reindex(df.index.append(splits).drop_duplicates().sort_values())
>>> df
Event Duration
2021-01-01 00:00:00 2.0 540.0
2021-01-01 09:00:00 1.0 180.0
2021-01-01 12:00:00 2.0 20.0
2021-01-01 12:20:00 1.0 1440.0
2021-01-02 00:00:00 NaN NaN
2021-01-02 12:20:00 2.0 60.0
2021-01-02 13:20:00 1.0 20.0
此时我们知道索引之间的差异才是我们想要的时间。填写Duration的空白,然后我们可以简单地按天/事件分组并求和,而不会出现任何意外行为:
>>> minutes = df.index.to_series().diff().shift(-1).astype('timedelta64[m]').fillna(df['Duration'])
>>> minutes
2021-01-01 00:00:00 540.0
2021-01-01 09:00:00 180.0
2021-01-01 12:00:00 20.0
2021-01-01 12:20:00 700.0
2021-01-02 00:00:00 740.0
2021-01-02 12:20:00 60.0
2021-01-02 13:20:00 20.0
dtype: float64
>>> minutes.groupby([df.index.date, df['Event'].ffill()]).sum()
Event
2021-01-01 1.0 880.0
2.0 560.0
2021-01-02 1.0 760.0
2.0 60.0
dtype: float64
请注意,我们还确保使用 .ffill() 将事件 ID 传播到分割线
此解决方案的优点是不会生成每分钟 1 个条目的巨大数据帧,并且对单个 Duration 值中可以包含多少天没有限制。