Python - 在数组中查找序列:当两个值低于阈值时开始,当两个值高于阈值时结束
Python - Find sequence in array: start when two values below threshold, end when two values above threshold
我有一个干旱指数 (PDSI) 的年度时间序列,其值范围从 -4 到 +4。我正在尝试定义一个干旱事件,该事件以连续两年低于 PDSI 值 0 开始,并在连续两年大于或等于 0 时结束。
比如这一系列的数据:
ts = [-2, -2, -4, 0, -1, 0, -1, 1, -2, 2, -3, -2, 3, 1, -2,
-3, -4, -3, 3, -3, -3, -3, -1, -3, 3, 3, -4, -1, -1, 0]
注意:我尝试张贴图片以帮助可视化问题,但我的声誉不够高
根据上面的干旱定义,这个系列应该有三个干旱:
1) 从第 0 年开始到第 11 年结束(第 12 和 13 年是 >=
0)
2) 从第 14 年开始到第 23 年结束(第 24 和 25 年 >=
0)
3) 从第 26 年开始到系列结束时:第 29 年。尽管这场干旱没有连续两年结束 >=
0,但它仍在进行中,应该计算在内。
return 值可以是一个数组,如:
droughts = [[0, 11], [14, 23], [26, 29]]
这意味着排除任何两个连续PDSI值<0的潜在子集。例如,在第一个序列[0, 11]中,[1,2]和[10,11]也满足'two consecutive values below the threshold' 规则。但是,它们应该被忽略,因为它们是更大序列的一部分。
编辑:
这里有一些代码可用于定义前两次干旱,但在最后一次上挂断了(我认为它会无限循环)。我是 Python 的新手,除此之外,代码无法正常工作,我猜它的效率也很低。
def find_droughts (array):
answer = []
i = 0
while i < len(array):
if (array[i] < 0 and array[i+1] < 0):
if i+1 >= len(array):
i = len(array)
end = i
a.append([start, end])
break
else:
start = i
print "start = %s" %start
for j in range(i+2, len(array)-1):
if (array[j] >= 0 and array[j+1] >= 0):
end = j-1
a.append([start, end])
print 'end=%s' %end
i = j+2;
break
else:
i += 1
else:
i += 1
return answer
find_droughts(ts)
和下面的输出。不得不中断内核,因为它陷入了循环。
start = 0
end=11
start = 14
end=23
start = 26
start = 27
start = 27
start = 27
start = 27
....
这样的事情怎么样:
ts = [-2, -2, -4, 0, -1, 0, -1, 1, -2, 2, -3, -2, 3, 1, -2,
-3, -4, -3, 3, -3, -3, -3, -1, -3, 3, 3, -4, -1, -1, 0]
# find positions of 2 consecutive negatives
neg = [i for i in range(len(ts)-1) if ts[i]<0 and ts[i+1] < 0]
print neg
# find locations of 2 consecutive positives + last year
pos = [i for i in range(len(ts)-1) if ts[i]>0 and ts[i+1] > 0] + [len(ts)]
print pos
# find the earliest neg for each pos
draughts = []
for p in pos:
try:
draughts.append((neg[0],p))
neg = [n for n in neg if n > p]
except IndexError:
# no more negatives left, no draught in progress
break
print draughts
输出:
[0, 1, 10, 14, 15, 16, 19, 20, 21, 22, 26, 27]
[12, 24, 30]
[(0, 12), (14, 24), (26, 30)]
有一些需要解决的问题和边缘情况,但总体而言...
这里有一个替代方法,只需要一次通过 ts
:
ts = [-2, -2, -4, 0, -1, 0, -1, 1, -2, 2, -3, -2, 3, 1, -2,
-3, -4, -3, 3, -3, -3, -3, -1, -3, 3, 3, -4, -1, -1, 0]
in_draught = False
draught = []
for i in range(len(ts)-1):
if in_draught and ts[i] > 0 and ts[i+1] > 0:
in_draught = False
draught.append(i)
elif not in_draught and ts[i] <0 and ts[i+1] < 0:
in_draught = True
draught.append(i)
if in_draught:
draught.append(len(ts)-1)
print [draught[i:i+2] for i in range(0,len(draught),2)]
输出:
[[0, 12], [14, 24], [26, 29]]
我有一个干旱指数 (PDSI) 的年度时间序列,其值范围从 -4 到 +4。我正在尝试定义一个干旱事件,该事件以连续两年低于 PDSI 值 0 开始,并在连续两年大于或等于 0 时结束。
比如这一系列的数据:
ts = [-2, -2, -4, 0, -1, 0, -1, 1, -2, 2, -3, -2, 3, 1, -2,
-3, -4, -3, 3, -3, -3, -3, -1, -3, 3, 3, -4, -1, -1, 0]
注意:我尝试张贴图片以帮助可视化问题,但我的声誉不够高
根据上面的干旱定义,这个系列应该有三个干旱:
1) 从第 0 年开始到第 11 年结束(第 12 和 13 年是 >=
0)
2) 从第 14 年开始到第 23 年结束(第 24 和 25 年 >=
0)
3) 从第 26 年开始到系列结束时:第 29 年。尽管这场干旱没有连续两年结束 >=
0,但它仍在进行中,应该计算在内。
return 值可以是一个数组,如:
droughts = [[0, 11], [14, 23], [26, 29]]
这意味着排除任何两个连续PDSI值<0的潜在子集。例如,在第一个序列[0, 11]中,[1,2]和[10,11]也满足'two consecutive values below the threshold' 规则。但是,它们应该被忽略,因为它们是更大序列的一部分。
编辑:
这里有一些代码可用于定义前两次干旱,但在最后一次上挂断了(我认为它会无限循环)。我是 Python 的新手,除此之外,代码无法正常工作,我猜它的效率也很低。
def find_droughts (array):
answer = []
i = 0
while i < len(array):
if (array[i] < 0 and array[i+1] < 0):
if i+1 >= len(array):
i = len(array)
end = i
a.append([start, end])
break
else:
start = i
print "start = %s" %start
for j in range(i+2, len(array)-1):
if (array[j] >= 0 and array[j+1] >= 0):
end = j-1
a.append([start, end])
print 'end=%s' %end
i = j+2;
break
else:
i += 1
else:
i += 1
return answer
find_droughts(ts)
和下面的输出。不得不中断内核,因为它陷入了循环。
start = 0
end=11
start = 14
end=23
start = 26
start = 27
start = 27
start = 27
start = 27
....
这样的事情怎么样:
ts = [-2, -2, -4, 0, -1, 0, -1, 1, -2, 2, -3, -2, 3, 1, -2,
-3, -4, -3, 3, -3, -3, -3, -1, -3, 3, 3, -4, -1, -1, 0]
# find positions of 2 consecutive negatives
neg = [i for i in range(len(ts)-1) if ts[i]<0 and ts[i+1] < 0]
print neg
# find locations of 2 consecutive positives + last year
pos = [i for i in range(len(ts)-1) if ts[i]>0 and ts[i+1] > 0] + [len(ts)]
print pos
# find the earliest neg for each pos
draughts = []
for p in pos:
try:
draughts.append((neg[0],p))
neg = [n for n in neg if n > p]
except IndexError:
# no more negatives left, no draught in progress
break
print draughts
输出:
[0, 1, 10, 14, 15, 16, 19, 20, 21, 22, 26, 27]
[12, 24, 30]
[(0, 12), (14, 24), (26, 30)]
有一些需要解决的问题和边缘情况,但总体而言...
这里有一个替代方法,只需要一次通过 ts
:
ts = [-2, -2, -4, 0, -1, 0, -1, 1, -2, 2, -3, -2, 3, 1, -2,
-3, -4, -3, 3, -3, -3, -3, -1, -3, 3, 3, -4, -1, -1, 0]
in_draught = False
draught = []
for i in range(len(ts)-1):
if in_draught and ts[i] > 0 and ts[i+1] > 0:
in_draught = False
draught.append(i)
elif not in_draught and ts[i] <0 and ts[i+1] < 0:
in_draught = True
draught.append(i)
if in_draught:
draught.append(len(ts)-1)
print [draught[i:i+2] for i in range(0,len(draught),2)]
输出:
[[0, 12], [14, 24], [26, 29]]