7.12 Identificação de eventos discretos
Frequentemente precisamos separar a série temporal de uma variável em eventos discretos, como a identificação de períodos extremos ou de risco, como secas, tempestades, ondas de calor, períodos de poluição atmosférica crítica (acima ou abaixo de um limiar de concentração do poluentes) e etc.
Para caracterização destes eventos as informação essencias são o início, o fim e a duração de cada evento. Com essas informações podemos identificar cada evento e extrair outros atributos, na escala de evento, para aprofundar a análise.
Para ilustrar a conveniência das funções vistas até agora, veremos uma forma geral para identificação de eventos. O evento de interesse será o período da estação chuvosa nos dados prec
. Neste exemplo, a estação chuvosa é definida quando prec > 100
mm mês-1.
O primeiro passo é identificar a ocorrência dos eventos.
limiar <- 100
# definição de evento (condição)
(x <- evts <- as.integer(prec > limiar))
#> [1] 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 1
A conversão dos eventos de lógico para numérico é opcional26 e foi usada apenas para facilitar a localização dos eventos visualmente (1: ocorrência de evento, 0: não ocorrência). A partir daí, o problema consiste em identificar sequências de elementos adjacentes iguais (sequências de 1 repetidos).
As posições iniciais de cada evento podem ser encontradas subtraindo o elemento prévio (lag(x)
) do elemento atual (x
). Se a diferença for -1
temos o início de um evento. A tabela abaixo permite visualizar melhor isso.
elemento | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
x | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
lag(x) | NA | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
pos_ini | NA | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | -1 | 1 | -1 |
# x atrasado: desloca os elementos para para frente
pos_ini <- which(lag(x) - x < 0)
# ajuste do primeiro elemento de pos_ini
pos_prim <- ifelse(
test = x[1] == 1,
yes = 1,
no = 0
)
(pos_ini <- c(pos_prim, pos_ini))
#> [1] 1 9 22 24
# datas de início dos eventos
dts[pos_ini]
#> [1] "2010-01-01" "2010-09-01" "2011-10-01" "2011-12-01"
Temos que ter cuidado especial com o primeiro índice das posições iniciais (pos_prim
), ajustando-o para considerar adequadamente eventos começando logo início do vetor. Esse ajuste é necessário porque usando a diferença do vetor defasado não há como detectar se o primeiro elemento é evento ou não.
Analogamente, as posições finais de cada evento podem ser encontradas subtraindo o elemento seguinte (lead(x)
) do elemento atual (x
). Quando essa diferença é -1
temos o fim de um evento, o que pode ser visualizado na tabela abaixo.
elemento | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
x | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
lead(x) | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | NA |
pos_fim | 0 | 0 | -1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | -1 | 0 | 0 | 0 | 0 | 0 | 1 | -1 | 1 | NA |
pos_fim <- which(lead(x) - x < 0)
# ajuste do último elemento de pos_fim
pos_ult <- ifelse(
test = x[length(x)] == 1,
yes = length(x),
no = 0
)
(pos_fim <- c(pos_fim, pos_ult))
#> [1] 3 15 22 24
# datas do fim dos eventos
dts[pos_fim]
#> [1] "2010-03-01" "2011-03-01" "2011-10-01" "2011-12-01"
O último índice do vetor de posições finais requer tratamento similar ao do 1° elemento das posições iniciais. Ele deve ser ajustado para tratar dos casos com eventos no último elemento de x
.
A duração de cada evento é facilmente obtida do fim e início de cada evento:
duracao <- pos_fim - pos_ini + 1
duracao
#> [1] 3 7 1 1
# rbind(x, atras = lag(x), adiant = lead(x), pos_ini = lag(x)-x, pos_fim = lead(x) - x)
Eventualmente você pode precisar de um vetor identificando cada evento, o que pode ser feito usando:
evts_id <- evts
evts_id[evts > 0] <- rep(seq_along(duracao), times = duracao)
evts_id
#> [1] 1 1 1 0 0 0 0 0 2 2 2 2 2 2 2 0 0 0 0 0 0 3 0 4
Este vetor pode ser usado, para obter estatísticas de cada evento. Por exemplo, a precipitação média em cada evento pode ser determinada passando este vetor como argumento da função tapply()
. Como só queremos informação nos eventos vamos substituir os valores = 0 por NA em evts_id
. Assim, a tapply()
retornará a média só para os eventos de interesse.
evts_id <- ifelse(evts_id == 0, NA, evts_id)
# prec média em cada evento
tapply(
X = prec,
INDEX = evts_id,
FUN = mean
)
#> 1 2 3 4
#> 198.3333 193.5714 120.0000 208.0000
A tapply()
tem três argumentos:
X
: dados que queremos aplicar a funçãoINDEX:
vetor de índices com os grupos para os quais a função será aplicada separadamente.FUN
: a função que desejamos aplicar aos dados (e.g.:mean()
, ``)
Isso significa que os resultados nos códigos abaixo não se alteram se removermos essa conversão.↩