29 jun 2023

Modelos de frecuencia mixta: autocompletar datos faltantes en la cola de una serie temporal en R

En la siguiente entrada se muestra como autocompletar la cola de variables con NA (fill missing values of time series). Es decir, tenemos una base de datos con información irregular, referidos a los NA o valores pendientes, la idea es desarrollar un proceso para completar los valores faltantes en la cola de esta base. Puntualmente, esto sirve cunado se están trabajando datos en frecuencia mixta, por ejemplo, mensual y trimestral, y tenemos por ejemplo dos meses de un trimestre, pero necesitamos proyectar el tercer mes para poder completar el trimestre. Puntualmente, dada la base:

t

X1

X2

t1

NA

NA

t2

NA

1

t2

NA

2

t4

8

3

t5

5

4

t6

3

5

t7

NA

6

T

NA

NA

En la primera serie quisiéramos proyectar dos valores, mientras que la segunda seria necesitaremos proyectar un valor, para finalmente tener una serie de valores con una colar regular como se muestra en la siguiente tabla:

t

X1

X2

t1

NA

NA

t2

NA

1

t2

NA

2

t4

8

3

t5

5

4

t6

3

5

t7

f11

6

T

f12

f21


Tenga pendiente que, en un sistema de pronóstico macroeconómico, esta forma de completar valores al final de la muestra no siempre es bueno, por lo que pueden buscarse otras opciones, dado que requerimos que estos ajustes cuenten una historia macroeconómica. Por ejemplo, si sabemos que la economía no esta bien, puede ser que el modelo arima estime una recuperación de las ventas, cuando nosotros sabemos que no se están recuperando. Entonces, más allá del ejercicio estadístico deben tenerse pendiente este tipo de consideraciones.

Usamos una data de valores trimestrales para la República Dominicana, llamada data_t_mes. Ahora veamos los extremos de esta data, para verificar que tiene valores NA en su cola:

data_t_mes[1:3] |>  head()
 
# A tibble: 6 x 3
  fecha               v_agro v_comu
  <dttm>               <dbl>  <dbl>
1 1991-01-01 00:00:00     NA     NA
2 1991-02-01 00:00:00     NA     NA
3 1991-03-01 00:00:00     NA     NA
4 1991-04-01 00:00:00     NA     NA
5 1991-05-01 00:00:00     NA     NA
6 1991-06-01 00:00:00     NA     NA
 
data_t_mes[1:3] |>  tail()
# A tibble: 6 x 3
  fecha               v_agro v_comu
  <dttm>               <dbl>  <dbl>
1 2023-04-01 00:00:00 12830. 13189.
2 2023-05-01 00:00:00    NA     NA
3 2023-06-01 00:00:00    NA     NA
4 2023-07-01 00:00:00    NA     NA
5 2023-08-01 00:00:00    NA     NA
6 2023-09-01 00:00:00    NA     NA

Retomando el objetivo de nuestra entrada, en R, creamos la siguiente función fill_missing_values. La misma permite autocompletar los valores na en la cola de cada columna/variable:

fill_missing_values <- function(x) {
  na_count <- cumsum(is.na(rev(x)))
  valores_NA_cola <- na_count[-length(na_count)][diff(na_count) == 0][1]
 
  if (valores_NA_cola>0) {
    ultima_posicion <- max(which(!is.na(x)))
    na_loc <- 1:length(x) %in% (ultima_posicion + 1):length(x) #posiciones_na_despues
   
    x_na <- x[na_loc]
   
    x[na_loc] <- exp(forecast::forecast(auto.arima(log(x), 
                                               ic ="aic", trace=F, stepwise = FALSE, parallel=TRUE
    ))$mean[length(x_na)])
  }
  return(x)
}

1.     Contar la cantidad de valores NA a proyectar en la cola de cada columna. La idea es revertir el valor de cada columna e ir contando los NA, entonces, en la primera posición donde se repitan los valores contabilizados, se entiende presenta la cantidad de NA en esa columna.

  na_count <- cumsum(is.na(rev(x)))
  valores_NA_cola <- na_count[-length(na_count)][diff(na_count) == 0][1]

Por ejemplo: x<-c(8,6,NA,NA) me regresará: NA, NA, 6, 8, entonces al hacer una suma de los NA, tendremos: 1,2,2,2 (recuerde que va contando NA). Entonces, buscamos la primera posición donde la diferencia de valores entre dos posiciones se hace cero: [diff(na_count) == 0][1].

2.     Usamos un condicional para identificar si hay que proyectar valores en dicha columna (valores_NA_cola>0).

3.     Identificamos la última posición con datos observados (max(which(!is.na(x)))). Y las posiciones donde están los NA que debemos proyectar ((ultima_posicion + 1):length(x)). Esto se hace para poder posteriormente colocar los valores proyectados en estas posiciones.

4.     Finalmente se utiliza un autoarima para proyectar el log(x) y colocar los valores proyectados en las posiciones de la variable identificada anteriormente (x[na_loc]).

Finalmente, podemos usar la función sobre una variable determinada:

fill_missing_values(data_t_mes$v_agro) |> tail()
[1]  12830.1 126836.9 126836.9 126836.9 126836.9 126836.9

O sobre una matriz de datos usando la función lapply:

data_t_mes[, -1] <- lapply(data_t_mes[, -1] , fill_missing_values)
 data_t_mes[1:3] |>  tail()
# A tibble: 6 x 3
  fecha                v_agro v_comu
  <dttm>                <dbl>  <dbl>
1 2023-04-01 00:00:00  12830. 13189.
2 2023-05-01 00:00:00 126837. 30878.
3 2023-06-01 00:00:00 126837. 30878.
4 2023-07-01 00:00:00 126837. 30878.
5 2023-08-01 00:00:00 126837. 30878.
6 2023-09-01 00:00:00 126837. 30878.

Agradecemos la colaboración de Cesar Diaz y ChapGPT para la elaboración de la función.

Creando variables por grupos en dplyr (group_by + mutate)

  Simulemos una base de hogares, donde se identifica el hogar, el sexo (1 mujer) y provincia y edad para cada miembro.   # Definir la lista ...