如何根据 pandas datetimeindex 划分我的 'timeconsume' 特征

How to partition my 'timeconsume' feature as per pandas datetimeindex

我的 pandas 5 分钟间隔数据框中有一个基于时间的特征,所以它看起来像

      dataDate               TimeconinSec

     2020-11-11 22:25:00     302
     2020-11-11 23:25:00     605
     2020-11-12 00:25:00     302

这个特征很少有超过 5 分钟(300 秒)的价值,所以我希望它像下面的输出一样,按时返回并分配时间特征

    dataDate               TimeconinSec

     2020-11-11 22:20:00     300
     2020-11-11 22:25:00     002
     2020-11-11 23:15:00     300
     2020-11-11 23:20:00     300
     2020-11-11 23:25:00     005
     2020-11-12 00:20:00     300 
     2020-11-12 00:25:00     002

我尝试了不同的 pandas 日期范围函数,但我如何才能跨时间间隔划分我的基于时间的特征

让我们首先将所有内容转换为正确的时间戳,并计算每个间隔的开始和结束:

>>> df['date'] = pd.to_datetime(df['dataDate'])
>>> df['since'] = (df['date'] - df['TimeconinSec'].astype('timedelta64[s]')).dt.floor(freq='300s')
>>> df['until'] = df['since'] + df['TimeconinSec'].astype('timedelta64[s]')

然后我们可以使用pd.date_range生成所有正确的中间区间边界:

>>> bounds = df.apply(lambda s: [*pd.date_range(s['since'], s['until'], freq='300s'), s['until']], axis='columns')
>>> bounds
0    [2020-11-11 22:15:00, 2020-11-11 22:20:00, 202...
1    [2020-11-11 23:10:00, 2020-11-11 23:15:00, 202...
2    [2020-11-12 00:15:00, 2020-11-12 00:20:00, 202...
dtype: object

然后用explode我们可以把它们做成自己的系列。我用了两次这个系列,一次是在间隔的开始,一次是在结束,所以转移了。请注意 groupby().shift() 允许仅在同一索引内执行移位。

>>> interval_ends = pd.concat([bounds.explode(), bounds.explode().groupby(level=0).shift(-1)], axis='columns', keys=['start', 'end'])
>>> interval_ends
                start                 end
0 2020-11-11 22:15:00 2020-11-11 22:20:00
0 2020-11-11 22:20:00 2020-11-11 22:20:02
0 2020-11-11 22:20:02                 NaT
1 2020-11-11 23:10:00 2020-11-11 23:15:00
1 2020-11-11 23:15:00 2020-11-11 23:20:00
1 2020-11-11 23:20:00 2020-11-11 23:20:05
1 2020-11-11 23:20:05                 NaT
2 2020-11-12 00:15:00 2020-11-12 00:20:00
2 2020-11-12 00:20:00 2020-11-12 00:20:02
2 2020-11-12 00:20:02                 NaT

之后我们可以丢弃索引并简单地计算每个间隔内的时间:

>>> interval_ends.reset_index(drop=True, inplace=True)
>>> delays = (interval_ends['end'] - interval_ends['start']).astype('timedelta64[s]')
>>> delays
0    300.0
1      2.0
2      NaN
3    300.0
4    300.0
5      5.0
6      NaN
7    300.0
8      2.0
9      NaN
dtype: float64

最后,我们只需加入以这些延迟和包含 NaNs 的下降线开始的间隔,我们就得到了您的最终结果:

>>> delays = delays.rename('time_in_secs').dropna().astype('int')
>>> interval_ends[['start']].join(delays, how='inner')
                start  time_in_secs
0 2020-11-11 22:15:00           300
1 2020-11-11 22:20:00             2
3 2020-11-11 23:10:00           300
4 2020-11-11 23:15:00           300
5 2020-11-11 23:20:00             5
7 2020-11-12 00:15:00           300
8 2020-11-12 00:20:00             2