我有一个为期一年的值的数据集,我要检测并计算连续值在预定阈值之上/之下的周期。我想简单地返回连续的上/下阈值的每个周期的长度。我在网上找到了几乎可以完全执行我想要的代码的代码(如下所示,该函数名为“ fire_season_length”),除了它在返回数据集结束之前(该年末)的最后连续时间段有困难。
我相信这个问题是因为只有在一系列值从阈值之上(以下)翻转到阈值之下(之上)时,才会报告一段连续的值。
这是我用来计算连续的上/下阈值周期的函数:
def fire_season_length(ts, threshold):
ntot_ts = ts.count() #total number of values in ts (timeseries)
n_gt_threshold = ts[ts >= threshold].count() #number of values greater than threshold
type_day = 0 #below threshold
type_day = 1 #meets or exceeds threshold
type_prev_day = 0 #initialize first day
storage_n_cons_days = [[],[]] #[[cons days above threshold], [cons days below threshold]]
n_cons_days = 0
for cur_day in ts: #current day in timeseries
if cur_day >= threshold:
type_cur_day = 1
if type_cur_day == type_prev_day: #if same as current day
n_cons_days += 1
else: #if not same as current day
storage_n_cons_days[1].append(n_cons_days)
n_cons_days = 1
type_prev_day = type_cur_day
else:
type_cur_day = 0
if type_cur_day == type_prev_day:
n_cons_days += 1
else:
storage_n_cons_days[0].append(n_cons_days)
n_cons_days = 1
type_prev_day = type_cur_day
return ntot_ts, n_gt_threshold, storage_n_cons_days
这是我通过函数运行时间序列时的输出; 我注释了该图以显示有7个周期的连续值,但返回的数组为[[13,185,30],[24、78、12]](表示[[阈值以上的周期] ,[[低于阈值的时间段]]])仅列出了六个这样的时间段。似乎输出中未报告时间段7,这与我在此功能中测试的其他时间序列的输出也一致。{{3 }}
所以我的问题是:即使一系列值没有翻转为另一个符号(高于/低于阈值),我如何获取代码以返回连续值的最终周期?
答案 0 :(得分:1)
您可以结合使用accumulate()和Counter():
import random
from itertools import accumulate
from collections import Counter
ts = [ random.randint(1,100) for _ in range(15) ]
treshold = 50
groups = accumulate([0]+[(a>=treshold) != (b>=treshold) for a,b in zip(ts,ts[1:])])
counts = sorted(Counter(groups).items())
above = [ c for n,c in counts if (n%2==0) == (ts[0]>=treshold) ]
below = [ c for n,c in counts if (n%2==0) != (ts[0]>=treshold) ]
print("data ",ts)
print("above",above)
print("below",below)
示例输出:
data [99, 49, 84, 69, 27, 88, 35, 43, 3, 48, 80, 14, 32, 97, 78]
above [1, 2, 1, 1, 2]
below [1, 1, 4, 2]
其工作方式如下: