代码之家  ›  专栏  ›  技术社区  ›  PyRsquared

当时间增量不是常数时,跟踪固定时间窗口内的观测值

  •  1
  • PyRsquared  · 技术社区  · 5 年前

    我有一个按时间索引的数据框,但观测之间的时间差不是常数。

    df
    >>>
        TimeStamp              x1        x2
    1   2015-03-01 19:05:01    0.812     18.23
    2   2015-03-01 19:22:17    0.121     13.91
    3   2015-03-01 19:24:34    0.822     15.10
    4   2015-03-01 19:28:53    0.093     22.38
    5   2015-03-01 21:49:57    0.291     22.90
    6   2015-03-01 23:59:01    0.672     23.12
    7   2015-03-02 02:30:01    0.421     28.56
    8   2015-03-02 02:30:01    0.591     31.72
    9   2015-03-02 02:31:17    0.811     21.71
    10  2015-03-02 04:37:19    0.142     16.39
    

    我想计算每个样本在固定时间窗口内的观察次数。

    如果我的时间窗口是10分钟,那么我想计算[0,2,1,0,0,0,2,1,0],因为在第一个样本的10分钟内观察到0个样本,在第二个样本的10分钟内观察到2个样本,在第三个样本的10分钟内观察到1个样本,等等。可能存在两个观察同时发生的情况,但它们是不同的观察结果(如7和8)。

    如果我的时间窗口是1小时,那么我想计算[3,2,1,0,0,0,2,1,0],因为在第一个样本的1小时内观察到3个样本,依此类推。

    我有一个函数可以做到这一点,但有两个问题;1) 它非常慢,因为它逐行遍历数据,2)有时返回的计数是负数,我发现这很奇怪,因为timedelta总是>=0

    import pandas as pd
    import datetime as dt
    
    def get_count(data: pd.DataFrame, window_hours: int, window_minutes: int) -> np.ndarray:
        # we only want to iterate to the sample that is within window_hours + window_minutes from the end
        last_sample = data["TimeStamp"].iloc[-1] - dt.timedelta(days=0, hours=window_hours, minutes=window_minutes)
        count = np.empty(len(data[data["TimeStamp"] <= last_sample]), dtype=int)
        i = 0
        for index, row in data[data["TimeStamp"] <= last_day].iterrows():
            idx = np.where(data["TimeStamp"] <= (row["TimeStamp"] + dt.timedelta(days=0, hours=window_hours, minutes=window_minutes)))[0][-1]
            tmp = idx - index
            count[i] = tmp
            i += 1
        return count
    

    有没有一种方法可以使用纯pandas/numpy(避免for循环)来实现这一点,从而使它更快,并提供我的方法似乎没有提供的所需输出?

    0 回复  |  直到 5 年前
        1
  •  0
  •   Rob Raymond    5 年前
    • 使用 面具 然后 count()
    • 灵活的,如args到 Timedelta
    df = pd.read_csv(io.StringIO("""   TimeStamp              x1        x2
    1   2015-03-01 19:05:01    0.812     18.23
    2   2015-03-01 19:22:17    0.121     13.91
    3   2015-03-01 19:24:34    0.822     15.10
    4   2015-03-01 19:28:53    0.093     22.38
    5   2015-03-01 21:49:57    0.291     22.90
    6   2015-03-01 23:59:01    0.672     23.12
    7   2015-03-02 02:30:01    0.421     28.56
    8   2015-03-02 02:30:01    0.591     31.72
    9   2015-03-02 02:31:17    0.811     21.71
    10  2015-03-02 04:37:19    0.142     16.39"""), sep="\s\s+", engine="python")
    
    df.TimeStamp = pd.to_datetime(df.TimeStamp)
    
    def within(dfa, **kwargs):
        return dfa.TimeStamp.apply(lambda t: dfa.loc[dfa.TimeStamp.gt(t) & 
                                                     dfa.TimeStamp.le(t+pd.Timedelta(**kwargs)),
                                                     "TimeStamp"].count())
    
    df["10min"] = within(df, minutes=10)
    df["4hour"] = within(df, hours=4)
    
    
    时间戳 x1 x2 10分钟 4小时
    1. 2015-03-01 19:05:01 0.812 18.23 0 4.
    2. 2015-03-01 19:22:17 0.121 13.91 2. 3.
    3. 2015-03-01 19:24:34 0.822 15.1 1. 2.
    4. 2015-03-01 19:28:53 0.093 22.38 0 1.
    5. 2015-03-01 21:49:57 0.291 22.9 0 1.
    6. 2015-03-01 23:59:01 0.672 23.12 0 3.
    7. 2015-03-02 02:30:01 0.421 28.56 1. 2.
    8. 2015-03-02 02:30:01 0.591 31.72 1. 2.
    9 2015-03-02 02:31:17 0.811 21.71 0 1.
    10 2015-03-02 04:37:19 0.142 16.39 0 0