每当 abs(difference) 自上一个样本超过阈值时,就对时间序列进行下采样

Downsample time series whenever abs(difference) since the previous sample exceeds threshold

我有一个日内逐笔股票价格的时间序列,随着时间的推移逐渐变化。每当有小的变化(例如价格上涨 0.01 美元)时,就会创建一行新数据。这会导致绘制速度非常慢的非常大的数据系列。我想缩减采样以便忽略小的变化(例如价格变为 up/down/up/down/up/down 并且在 50 行数据后保持不变),这样可以提高绘图速度而不牺牲图形的定性准确性。我只想在价格上涨 up/up/up/up 时进行抽样,因此我只显示明显的变化。

import pandas as pd
import numpy as np
prices = pd.DataFrame(np.random.randint(0,1000, size=(100, 1))/100+1000, columns=list('A'))

我希望在与前一个样本的差异超过某个阈值时进行采样。因此,我将默认对第 0 行进行采样。如果第 1、2、3 和 4 行离第 0 行太近,我想把它们扔掉。然后,如果第 5 行距离第 0 行足够远,我将对其进行采样。然后,第 5 行成为我的新锚点,我将重复上面描述的相同过程。

有没有办法做到这一点,最好没有循环?

您可以应用 down-sampling 屏蔽函数来检查是否超出了距离。然后将其用于 select 到 select 适用的行。

这里是 down-sampling 屏蔽函数:

def down_mask(x, max_dist=3):
    global cum_diff
    
    # if NaN return True
    if x!=x:
        return True
    
    cum_diff += x
    if abs(cum_diff) > max_dist:
        cum_diff = 0
        return True
    
    return False
    

然后应用它并将其用作掩码以获取所需的条目:

cum_diff = 0

df[df['prices'].diff().apply(down_mask, max_dist=5)]

     prices
0   1002.07
1   1007.37
2   1000.09
6   1008.08
10  1001.57
14  1006.74
18  1000.42
19  1006.98
21  1001.30
26  1008.89
28  1003.77
38  1009.04
40  1000.52
44  1007.06
47  1001.21
48  1009.38
49  1001.81
51  1008.64
52  1002.72
55  1008.84
56  1000.86
57  1007.17
67  1001.31
68  1006.33
79  1001.14
98  1009.74
99  1000.53

不完全是要求的。我提供了两个选项,一个是阈值,一个是阈值和一个滑动周期。

import pandas as pd
import numpy as np

prices = pd.DataFrame(np.random.randint(0,1000, size=(100, 1))/100+1000, columns=list('A'))

threshold_ = 3
index = np.abs(prices['A'].values[1:] - prices['A'].values[:-1]) > threshold_
index = np.insert(index, 0, True)

print(prices[index == True], len(prices[index == True]))

period = 5
hist = len(prices)
index = np.abs(prices['A'].values[period:] - prices['A'].values[:hist-period]) > threshold_
index = np.insert(index, 0, np.empty((1,period), dtype=bool)[0])

print(prices[index == True], len(prices[index == True]))