如何根据 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
最后,我们只需加入以这些延迟和包含 NaN
s 的下降线开始的间隔,我们就得到了您的最终结果:
>>> 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
我的 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
最后,我们只需加入以这些延迟和包含 NaN
s 的下降线开始的间隔,我们就得到了您的最终结果:
>>> 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