Python - 在数组中查找序列:当两个值低于阈值时开始,当两个值高于阈值

时间:2015-09-09 18:36:58

标签: python sequence

我有一个干旱指数(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结束,但它仍然在进行中,应该计算在内。

返回值可以是如下数组:

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

这意味着排除具有两个连续PDSI值的潜在子集<1。例如,在第一个序列[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
....

1 个答案:

答案 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]

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