2015-09-09 33 views
1

我有干旱指数(PDSI)的年度时间序列,值范围从-4到+4。我试图定义一个干旱事件,该事件始于连续两年低于PDSI值0,并在连续两年大于或等于0时结束。Python - 在数组中查找序列:当两个值低于阈值时开始,当两个值高于阈值时结束

例如,在此系列数据中:

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年结束。尽管这种干旱并未连续两年结束,但它仍在进行中,应该计算在内。

返回值可以是一个数组,如:

droughts = [[0, 11], [14, 23], [26, 29]] 

这意味着排除任何潜在的子集与PDSI < 0例如两个连续的值,第一序列[0,11],它是也确实[1,2]和[10,11]满足'阈值以下的两个连续值'规则。但是,它们应该被忽略,因为它们是更大序列的一部分。

编辑:

下面是一些代码,用于定义前两个干旱的作品,但得到挂在最后一个(我认为这是无限循环)。我对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 
.... 
+0

欢迎的StackOverflow!你尝试过什么吗?如果是,你能显示代码吗? –

+0

我不明白这个逻辑是如何工作的 - 就像什么时候门槛没有满足两年的负面情况一样 - 即[10,11]是否也符合要求? – mauve

+0

@mauve,你好!虽然[10,11]都低于零,但它们仍应算作第一次干旱事件的一部分,自第0年开始,因为[0,1] = -2,-2。当且仅当连续两年> = 0时,第一次干旱事件应该停止。在这种情况下,年限[12,13]。不过,我希望输出结果不包括[12,13]作为干旱序列的一部分。相反,序列的最终值应该是11. – Matt

回答

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] 

# 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]] 
+0

非常感谢!它在一些真实的数据上工作得很好。作为一名Python新手,我需要一些时间来弄清楚你的解决方案在做什么。 – Matt

相关问题