【问题标题】:Slice pandas timeseries relative to condition相对于条件切片 pandas 时间序列
【发布时间】:2020-01-12 06:12:22
【问题描述】:

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

现在,我在整个数据帧上使用 .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)

【问题讨论】:

    标签: pandas datetime slice


    【解决方案1】:

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

    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”,

    ts['Signal'].iloc[1000] = 1
    

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

     In[1]: ts.index.is_monotonic_increasing
    Out[1]: True
    

    导入tqdm 以衡量性能

    from tqdm import tqdm
    

    两个选项,由于时间序列的分辨率是1分钟,所以这里的结果是一样的,但是你可以根据你期望的结果使用一个或另一个。

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

    D = pandas.Timedelta('00:00:60')
    sequences = []
    
    for timestamp, row in tqdm(ts.iterrows()):
        if ts.loc[timestamp:timestamp + D, 'Signal'].sum() > 0: 
            break
        sequences.append(ts.loc[timestamp:timestamp + D])
    

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

    两次执行都低于一秒,但如果您正在寻求更快的性能,您可以查看.itertuples()(参考https://medium.com/@formigone/stop-using-df-iterrows-2fbc2931b60e

    【讨论】:

    • @Rob 您有机会查看答案吗?
    • 嗨,很抱歉回答迟了。我决定处理这个有点不同,但从你的答案 nr 中使用了很多。 1
    • 不用担心,很高兴知道它有点帮助!
    【解决方案2】:

    这很有效,不过对于大数据集来说有点慢

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-09
      • 2021-01-03
      • 1970-01-01
      • 2014-11-09
      • 2012-07-03
      • 2018-01-10
      • 2021-12-24
      • 2019-05-19
      相关资源
      最近更新 更多