Последовательные события ниже порога - PullRequest
2 голосов
/ 08 мая 2019

У меня есть ряды SPI длиной 324 и значениями от -3 до +3.Я хочу получить индексы мест, где 3 или более последовательных временных шага находятся ниже порога -1

Я тщательно искал этот сайт и в других местах без особого успеха, например, Проверьте, есть ли 3 последовательных значения вмассив, который находится выше некоторого порога , но не выполняет именно то, что я хочу

Assuming this is what I want to do
th = -1 # threshold

a = [-3,4,5,-1,-2,-5,1,4,6,9,-3,-3,-1,-2,4,1,4] # my data

a[x]<th and a[x+1]<th and a[x+2]<th # find 3 or more consecutive   
time below threshold 

in this case that will be event e1=[-1,-2,-5] and e2=[-3,-3,-1,-2]

next I want to count this
counts = [len(e1),len(e2)] = [3,4]
Sum = [np.sum(e1),np.sum(e2)] = [-8, -9]

Это то, что я хочу сделать, и помощь действительно будет оценена, спасибо

Ответы [ 3 ]

2 голосов
/ 08 мая 2019

Вот пошаговый рецепт с комментариями.

a = [-3,4,5,-1,-2,-5,1,4,6,9,-3,-3,-1,-2,4,1,4]
th = -1
a = np.array(a)

# create mask of events; find indices where mask switches
intervals = np.where(np.diff(a<=th, prepend=0, append=0))[0].reshape(-1,2)

# discard short stretches
intervals = intervals[np.subtract(*intervals.T) <= -3]

intervals
# array([[ 3,  6],
#        [10, 14]])

# get corresponding data
stretches = np.split(a, intervals.reshape(-1))[1::2]

stretches
# [array([-1, -2, -5]), array([-3, -3, -1, -2])]

# count events
-np.subtract(*intervals.T)
# array([3, 4])

# sum events
np.add.reduceat(a, intervals.reshape(-1))[::2]
# array([-8, -9])
2 голосов
/ 08 мая 2019

Поскольку вы пометили панд:

s = pd.Series([-3,4,5,-1,-2,-5,1,4,6,9,-3,-3,-1,-2,4,1,4])

# thresholding
a = (s<1)

# blocks
b = (a!=a.shift()).cumsum()

# groupby
df = s[a].groupby(b).agg([list,'size','sum'])
df = df[df.size>=3]

Вывод

           list      size   sum
3       [-1, -2, -5]    3   -8
5   [-3, -3, -1, -2]    4   -9
1 голос
/ 08 мая 2019

С np.logical_and.reduce + shift, проверка последовательных строк ниже порога. Затем группа, чтобы получить все необходимые вам агрегаты:

import numpy as np
import pandas as pd

def get_grps(s, thresh=-1, Nmin=3):
    """
    Nmin : int > 0
        Min number of consecutive values below threshold.
    """
    m = np.logical_and.reduce([s.shift(-i).le(thresh) for i in range(Nmin)])
    if Nmin > 1:
        m = pd.Series(m, index=s.index).replace({False: np.NaN}).ffill(limit=Nmin-1).fillna(False)
    else:
        m = pd.Series(m, index=s.index)

    # Form consecutive groups
    gps = m.ne(m.shift(1)).cumsum().where(m)

    # Return None if no groups, else the aggregations
    if gps.isnull().all():
        return None
    else:
        return s.groupby(gps).agg([list, sum, 'size']).reset_index(drop=True)

get_grps(pd.Series(a))
#               list  sum  size
#0      [-1, -2, -5]   -8     3
#1  [-3, -3, -1, -2]   -9     4

get_grps(pd.Series(a), thresh=-1, Nmin=1)
#               list  sum  size
#0              [-3]   -3     1
#1      [-1, -2, -5]   -8     3
#2  [-3, -3, -1, -2]   -9     4

get_grps(pd.Series(a), thresh=-100, Nmin=1)
#None
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...