问题描述
我有一个时间序列,中间有休息时间(没有录音的时间)。一个简化的例子是:
df = pd.DataFrame(
np.random.rand(13),columns=["values"],index=pd.date_range(start='1/1/2020 11:00:00',end='1/1/2020 23:00:00',freq='H'))
df.iloc[4:7] = np.nan
df.dropna(inplace=True)
df
values
2020-01-01 11:00:00 0.100339
2020-01-01 12:00:00 0.054668
2020-01-01 13:00:00 0.209965
2020-01-01 14:00:00 0.551023
2020-01-01 18:00:00 0.495879
2020-01-01 19:00:00 0.479905
2020-01-01 20:00:00 0.250568
2020-01-01 21:00:00 0.904743
2020-01-01 22:00:00 0.686085
2020-01-01 23:00:00 0.188166
现在我想把它分成间隔,这些间隔除以某个时间跨度(例如 2 小时)。在上面的例子中,这将是:
( values
2020-01-01 11:00:00 0.100339
2020-01-01 12:00:00 0.054668
2020-01-01 13:00:00 0.209965
2020-01-01 14:00:00 0.551023,values
2020-01-01 18:00:00 0.495879
2020-01-01 19:00:00 0.479905
2020-01-01 20:00:00 0.250568
2020-01-01 21:00:00 0.904743
2020-01-01 22:00:00 0.686085
2020-01-01 23:00:00 0.188166)
我有点惊讶,因为我认为这是一个常见问题,所以我没有找到任何相关信息。我当前获取每个间隔的开始和结束索引的解决方案是:
def intervals(data: pd.DataFrame,delta_t: timedelta = timedelta(hours=2)):
data = data.sort_values(by=['event_timestamp'],ignore_index=True)
breaks = (data['event_timestamp'].diff() > delta_t).astype(bool).values
ranges = []
start = 0
end = start
for i,e in enumerate(breaks):
if not e:
end = i
if i == len(breaks) - 1:
ranges.append((start,end))
start = i
end = start
elif i != 0:
ranges.append((start,end))
start = i
end = start
return ranges
有什么建议可以让我以更聪明的方式做到这一点吗?我怀疑这应该可以使用 groupby
实现。
解决方法
是的,您可以使用非常方便的np.split
:
dt = pd.Timedelta('2H')
parts = np.split(df,np.where(np.diff(df.index) > dt)[0] + 1)
例如:
>>> parts
[ values
2020-01-01 11:00:00 0.557374
2020-01-01 12:00:00 0.942296
2020-01-01 13:00:00 0.181189
2020-01-01 14:00:00 0.758822,values
2020-01-01 18:00:00 0.682125
2020-01-01 19:00:00 0.818187
2020-01-01 20:00:00 0.053515
2020-01-01 21:00:00 0.572342
2020-01-01 22:00:00 0.423129
2020-01-01 23:00:00 0.882215]
,
@Pierre 感谢您的投入。我现在找到了一个对我来说很方便的解决方案:
df['diff'] = df.index.to_series().diff()
max_gap = timedelta(hours=2)
df['gapId'] = 0
df.loc[df['diff'] >= max_gap,['gapId']] = 1
df['gapId'] = df['gapId'].cumsum()
list(df.groupby('gapId'))
给出:
[(0,values date diff gapId
0 1.0 2020-01-01 11:00:00 NaT 0
1 1.0 2020-01-01 12:00:00 0 days 01:00:00 0
2 1.0 2020-01-01 13:00:00 0 days 01:00:00 0
3 1.0 2020-01-01 14:00:00 0 days 01:00:00 0),(1,values date diff gapId
7 1.0 2020-01-01 18:00:00 0 days 04:00:00 1
8 1.0 2020-01-01 19:00:00 0 days 01:00:00 1
9 1.0 2020-01-01 20:00:00 0 days 01:00:00 1
10 1.0 2020-01-01 21:00:00 0 days 01:00:00 1
11 1.0 2020-01-01 22:00:00 0 days 01:00:00 1
12 1.0 2020-01-01 23:00:00 0 days 01:00:00 1)]