【问题标题】:Split time series in intervals of non-uniform length以非均匀长度的间隔分割时间序列
【发布时间】:2021-05-10 14:53:13
【问题描述】:

我有一个时间序列,中间有休息时间(没有录音的时间)。一个简化的例子是:

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 以某种方式实现。

【问题讨论】:

  • 为什么您的示例中只有两个组?第二组跨越 5 小时。为什么14:00:00 消失了?
  • 哦,等等,我想我现在明白了:您想在超过某个阈值持续时间的地方进行拆分。不过,不确定14:00 发生了什么,可能是疏忽?
  • 哦,是的 14:00 是个错误。

标签: python pandas dataframe time-series intervals


【解决方案1】:

可以,你可以用很方便的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]

【讨论】:

    【解决方案2】:

    @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)]
    

    【讨论】:

      猜你喜欢
      • 2022-08-03
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      • 2014-03-12
      相关资源
      最近更新 更多