每当 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]))
我有一个日内逐笔股票价格的时间序列,随着时间的推移逐渐变化。每当有小的变化(例如价格上涨 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]))