Pandas 与条件相关的时间序列

Pandas 与条件相关的时间序列,pandas,datetime,slice,Pandas,Datetime,Slice,我需要在条件发生前60分钟对时间序列进行切片,例如,在列“信号”==1中的数字之前60秒 现在,我在整个数据帧上使用.tail(60),直到达到所需的索引,但这是非常低效的 def create_sequences(signal, label, data): """Function to return seqs of 60 secs prior to condition""" sequences = [] for i in signal: sequen

我需要在条件发生前60分钟对时间序列进行切片,例如,在列“信号”==1中的数字之前60秒

现在,我在整个数据帧上使用.tail(60),直到达到所需的索引,但这是非常低效的

def create_sequences(signal, label,  data):
    """Function to return seqs of 60 secs prior to condition"""
    sequences = []

    for i in signal:
        sequence = data.loc[:i].tail(60)
        if len(sequence) == 60:
            sequences.append((np.array(sequence.drop('Signal', 
                                       axis=1)).transpose(), label))


    return sequences


# To generate some data for reproduction
periods = 7 * 24 * 60
tidx = pd.date_range('2019-09-01', periods=periods, freq='T')
ts = pd.DataFrame(data=data, index=tidx)
ts['Signal'] = ts[0].apply(lambda x: 1 if x > 0 else 0)

ones = ts[ts.Signal == 1].index.values


x = create_sequences(ones, 1, ts)

我稍微修改了数据生成脚本

periods = 7 * 24 * 60
tidx = pandas.date_range('2019-09-01', periods=periods, freq='T')
ts = pandas.DataFrame(index=tidx)
ts['Signal'] = 0
并在第1000行(超过10080行)中引入了“1”

首先,快速检查时间戳索引是否已排序

 In[1]: ts.index.is_monotonic_increasing
Out[1]: True
导入
tqdm
以测量性能

from tqdm import tqdm
两个选项,由于时间序列的分辨率为1分钟,因此此处的结果相同,但您可以使用其中一个选项,具体取决于预期的结果

1.如果希望生成的切片像滑动窗口一样重叠,可以使用
.iterrows()

2.如果希望生成的切片是连续的且不重叠

D = pandas.Timedelta('00:00:60')
sequences = []

nmax = numpy.trunc((ts.index.max() - ts.index.min()) / D)

for n in range(0, int(nmax)):
  if ts.loc[ts.index.min() + (n * D):ts.index.min()  + (1 + n) * D, 'Signal'].sum() > 0: 
    break
  sequences.append(ts.loc[ts.index.min() + (n * D):ts.index.min()  + (1 + n) * D])

两次执行都低于1秒,但如果您想获得更快的性能,可以检查
.itertuples()
(参考)。

这是可行的,但对于大型数据集来说有点慢

sequences = []
for timestamp, row in ts.iterrows():

    data = ts.loc[timestamp:timestamp + pd.Timedelta(seconds=60),:]
    label = ts.Signal.loc[timestamp + pd.Timedelta(seconds=60)]
    sequences.append((ts.drop('Signal', axis=1).values, label))

@Rob你有机会复习一下答案吗?嗨,很抱歉回答晚了。我决定对此有点不同,但使用了大量您的答案1无需担心,很高兴知道这有点帮助!
D = pandas.Timedelta('00:00:60')
sequences = []

nmax = numpy.trunc((ts.index.max() - ts.index.min()) / D)

for n in range(0, int(nmax)):
  if ts.loc[ts.index.min() + (n * D):ts.index.min()  + (1 + n) * D, 'Signal'].sum() > 0: 
    break
  sequences.append(ts.loc[ts.index.min() + (n * D):ts.index.min()  + (1 + n) * D])
sequences = []
for timestamp, row in ts.iterrows():

    data = ts.loc[timestamp:timestamp + pd.Timedelta(seconds=60),:]
    label = ts.Signal.loc[timestamp + pd.Timedelta(seconds=60)]
    sequences.append((ts.drop('Signal', axis=1).values, label))