18 abr 2024

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 de relaciones familiares por hogar
hogar <- c(1,1,1,1,2,2,2,3,4,4,4)
 prov <- c("a","a","a","a","c","c","c","a","b","b","b")
   id <- 1:length(hogar)
mujer <- c(1,0,1,1,0,0,2,0,1,0,0)
 edad <- c(28,29,10,8,33,27,13,24,32,11,6)
 
hogar_data <- data.frame(id, hogar, prov, mujer, edad)
hogar_data
  id hogar prov mujer edad
1   1     1    a     1   28
2   2     1    a     0   29
3   3     1    a     1   10
4   4     1    a     1    8
5   5     2    c     0   33
6   6     2    c     0   27
7   7     2    c     2   13
8   8     3    a     0   24
9   9     4    b     1   32
10 10     4    b     0   11
11 11     4    b     0    6
 
Si combinanos group_by con summarise, obtendríamos un collapse de la base de datos, con la edad promedio del grupo indicado en group_by. Es decir, pasamos a tener tantas observaciones como hogares en nuestra base de datos. Noten que en este caso solo quedan aquellas variables a las que le hemos indicado la forma de agregación.
 
hogar_data |>
  group_by(hogar) |>
  summarise(mean(edad))
 
# A tibble: 4 x 2
  hogar `mean(edad)`
  <dbl>        <dbl>
1     1         18.8
2     2         24.3
3     3         24 
4     4         16.3
 
Ahora, en lugar de obtener el resumen anterior, quisiéramos agregar una variable que indique la edad promedio por hogar. Podemos combinar group_by + mutate. Ahora agregamos una variable con la edad promedio de cada hogar.
 
hogar_data |>
  group_by(hogar) |>
  mutate(edad_mhogar = mean(edad))
 
# A tibble: 11 x 6
# Groups:   hogar [4]
      id hogar prov  mujer  edad edad_mhogar
   <int> <dbl> <chr> <dbl> <dbl>       <dbl>
 1     1     1 a         1    28        18.8
 2     2     1 a         0    29        18.8
 3     3     1 a         1    10        18.8
 4     4     1 a         1     8        18.8
 5     5     2 c         0    33        24.3
 6     6     2 c         0    27        24.3
 7     7     2 c         2    13        24.3
 8     8     3 a         0    24        24 
 9     9     4 b         1    32        16.3
10    10     4 b         0    11        16.3
11    11     4 b         0     6        16.3
 
Contar número de menores de edad en cada hogar. Contar la cantidad de menores de edad en cada hogar.
 
hogar_data |>
  group_by(hogar) |>
  mutate(num_menores = sum(edad < 18))
 
# A tibble: 11 x 6
# Groups:   hogar [4]
      id hogar prov  mujer  edad num_menores
   <int> <dbl> <chr> <dbl> <dbl>       <int>
 1     1     1 a         1    28           2
 2     2     1 a         0    29           2
 3     3     1 a         1    10           2
 4     4     1 a         1     8           2
 5     5     2 c         0    33           1
 6     6     2 c         0    27           1
 7     7     2 c         2    13           1
 8     8     3 a         0    24           0
 9     9     4 b         1    32           2
10    10     4 b         0    11           2
11    11     4 b         0     6           2
 
Contar el numero de menores de edad que son mujeres.
 
hogar_data |>
  group_by(hogar) |>
  mutate(num_menores = sum(edad < 18 & mujer ==1))
 
# A tibble: 11 x 6
# Groups:   hogar [4]
      id hogar prov  mujer  edad num_menores
   <int> <dbl> <chr> <dbl> <dbl>       <int>
 1     1     1 a         1    28           2
 2     2     1 a         0    29           2
 3     3     1 a         1    10           2
 4     4     1 a         1     8           2
 5     5     2 c         0    33           0
 6     6     2 c         0    27           0
 7     7     2 c         2    13           0
 8     8     3 a         0    24           0
 9     9     4 b         1    32           0
10    10     4 b         0    11           0
11    11     4 b         0     6           0

11 abr 2024

20 ejemplos de Indexación de un vector en R

Entenderemos indexación acceder a una parte de un objeto. Recordemos que, en R, tenemos objetos atómicos (de un solo tipo de clases, por ejemplo, solo números, o solo texto) y recursivos. Estos combinaban diferentes objetos con formas distintas, por ejemplo, texto y números. Según chatGPTen R, "indexar" se refiere a acceder a elementos específicos de un vector, matriz, lista o data frame utilizando su posición numérica o su nombre. Indexar te permite extraer o modificar valores individuales o conjuntos de valores de una estructura de datos”.

 INDEXACIÓN NUMÉRICA

En el caso de la indexación numérica, accedemos a parte de ese vector indicando a cuál posición deseamos acceder. Debajo colocamos diferentes ejemplos usando el vector edad.

Ej. 1: La primera posición, colocamos corchetes [] posterior al vector que contienen los elementos al cual queremos acceder (edad en este caso).

edad <- c(17,22,31,14,12)
edad[1]
[1] 17

Ej. 2: Si el número se coloca en negativo, indica que no queremos acceder a esa parte del vector. Regresa todo, menos la posición indicada con menos.

edad[-1]
[1] 22 31 14 12

Ej. 3: Igual podemos acceder a múltiples posiciones de un vector, colocando un vector de números entre los corchetes. Si repites el 1 varias veces te regresara la posición 1 cuantas veces como repitas el 1.

> edad[c(1,4)]
[1] 17 14

Ej. 4: Acceder a la última posición de un vector usando la función length.

edad[length(edad)]
[1] 12

Ej. 5: Igual podemos usar el operador dos puntos para generar una secuencia. Sí le indicamos esta secuencia a R, entonces regresa las posiciones del vector que están dentro de la misma.

edad[1:3]
[1] 17 22 31

Ej. 6: imaginemos ahora que queremos acceder a las dos ultimas posiciones del vector, podemos indicar la longitud de la misma:

edad[c(4,5)]
[1] 14 12

Ej. 7: No obstante, el ejemplo anterior deja de funcionar si agregamos datos al vector anterior:

edad <- c(edad, 14,24)
[1] 17 22 31 14 12 14 24


edad[(length(edad)-1):length(edad)]
[1] 14 24

Ej. 8: Entonces, si queremos eliminar las dos ultimas posiciones de un vector, colocamos el signo de menos delante de la secuencia.

edad[-c((length(edad)-1):length(edad))]
[1] 17 22 31 14 12

INDEXACIÓN LÓGICA 

En este caso colocamos un vector lógico entre corchetes, en lugar de números. Este permite acceder a elementos que cumplen con alguna condición, sin importar donde estén colocados los mismos.

Ej. 9: Llamar a los menores de edad.

 edad[edad<18]
[1] 17 14 12 14

Ej. 10: Llamar a los que tienen edades entre 5-15 años.

edad[edad>=5 & edad<=15]
[1] 14 12 14

Ej. 11: Podemos indexar a partir de la información de un segundo vector. Supongamos tenemos el vector mujer que indica el sexo de las personas. Entonces podemos recuperar las edades de las mujeres.

mujer<-c(1,0,1,0,1,0,0)
edad[mujer==1]
[1] 17 31 12

Tener pendiente que, si usas esta variable directamente para indexar el vector, este te regresara la primera posición tantas veces como se repita en el vector numérico mujer. Recuerde que este es un vector numérico.

edad[c(1,1,1)]
[1] 17 17 17


edad[mujer]
[1] 17 17 17

Por tanto, si se quiere usar directamente, se debe definir como un vector lógico.

mujer1<-c(T,F,T,F,T,F,F)
edad[mujer1]

OTROS EJEMPLOS

Ej. 12: Indexar utilizando nombres asignados a los datos.

nombres <- c("Ana", "Pedro", "Juana", "Johan", "Lia", NA, "Julio")
names(edad) <- nombres
edad
  Ana Pedro Juana Johan   Lia  <NA> Julio
   17    22    31    14    12    14    24
 
edad["Juana"]
Juana
   31

Ej. 13:  Combinar vectores. Mujeres menores de edad. Si colocamos el 0, se elegirían mujeres o menores de edad.

edad[mujer==1 & edad<=17]
Ana Lia
 17  12

Como se puede ver hasta aquí, solo es cuestión de usar adecuadamente los operadores lógicos, que vimos en la clase 1.

Ej. 14: acceder a una secuencia de posiciones.

Esta forma de generar secuencias igual nos permite acceder por ejemplo a todas las posiciones pares, 2,4,6,…. Pensar en alguna aplicación, imagine tiene una data mensual, y desea acceder a los meses 1,4,7,10… Para esto usamos la función seq.

1:5
[1] 1 2 3 4 5
 
seq(1,5, by = 1)
[1] 1 2 3 4 5

En el siguiente ejemplo accederá a las posiciones entre 1 y 7, iniciando en 1 y avanzando de 2 en e2. 1,3,4…

edad[seq(1, length(edad), by = 2)]
  Ana Juana   Lia Julio
   17    31    12    24

Ej. 15: Ordenar de menor a mayor. Como orden regresa la posición que ocupa cada elemento en un vector determinado, caminando de menor a mayor. Como podemos ver en el ejemplo siguiente, se verifica la salida de order, 5, 4, 6, … indica que el menor valor se encuentra en la posición 5 del vector, el segundo menor, en la posición 4, y así de forma sucesiva.

edad
  Ana Pedro Juana Johan   Lia  <NA> Julio
   17    22    31    14    12    14    24
 
order(edad)
[1] 5 4 6 1 2 7 3

Ahora, podemos obtener un vector ordenado de menor a mayor edad.

edad[order(edad)]
  Lia Johan  <NA>   Ana Pedro Julio Juana
   12    14    14    17    22    24    31

 Igual, podemos obtener los nombres, ordenados del menor al mayor.

nombres[order(edad)]
[1] "Lia"   "Johan" NA      "Ana"   "Pedro" "Julio" "Juana" 

Ej. 16: acceder al mínimo y máximo usando order. Solo debemos acceder a las posiciones extremas.

Persona con menor edad.

edad[order(edad)[1]]
Lia
 12

Persona con mayor edad.

edad[order(edad)[length(edad)]]
Juana
   31

Ej. 17: Indexación con which. Este comando regresa la posición donde la variable cumple con una determinada condición. Por ejemplo, identificar la posición donde se encuentra la persona con la edad mínima.

which(edad==min(edad))
Lia
  5

Entonces, podemos usar esta coordenada para poder recuperar la edad mínima disponible en la data. Antes vimos en qué posición estaba, ahora vemos cual es su edad.

edad[which(edad==min(edad))]
Lia
 12

Ej. 18: Podemos seleccionar múltiples nombres usando el operador contenido en. El mismo permite indicar un conjunto de nombres, para posteriormente, buscar estos nombres en el vector de edad.

personas_seleccionadas <- c("Ana", "Lia", "Julio")
edad[names(edad) %in% personas_seleccionadas]
Ana   Lia Julio
   17    12    24

Ej. 19: Acceder a las edades correspondientes a los nombres que no son NA.

edad[!is.na(names(edad))]
  Ana Pedro Juana Johan   Lia Julio
   17    22    31    14    12    24

Ej. 20: Igual podemos usar la indexación para modificar valores de un vector. Podemos verificar que un nombre es NA, entonces podemos identificar ese NA y cambiarlo por Walker.

nombres[is.na(nombres)] <- "Walker"
names(edad) <- nombres
edad
   Ana  Pedro  Juana  Johan    Lia Walker  Julio
    17     22     31     14     12     14     24

Ahora vamos a sustituir la edad de Walker, por 16 años. Debido a que el se cambio la edad cuando jugaba pelota. Le quitaron dos años.

edad[nombres == "Walker"] <- 16
edad
   Ana  Pedro  Juana  Johan    Lia Walker  Julio
    17     22     31     14     12     16     24 

Espero les haya sido de utilidad… Gracias por visitarnos.

10 abr 2024

Midiendo la persistencia de una serie temporal en R a partir de un Autoregresivo

Suponga que el promedio de una serie temporal es el valor de referencia de largo plazo de la misma, la persistencia mide el tiempo medio que tarda una serie en regresar a ese nivel medio. En la siguiente figura se simulan en R dos series temporales con distintos grados de persistencia, asumiendo que una aproximación se puede obtener a partir del coeficiente autoregresivo de primer orden de la serie, verificándose que la serie con mayor coeficiente, pasa menor cantidad de veces por su promedia y tarda más tiempo en regresar posterior a un choque.

# Establecer semilla para reproducibilidad
set.seed(123)
library(ggplot)
 
# Número de observaciones
n <- 100
 
# Media y desviación estándar de las series
media <- 0
volatilidad <- 1
 
# Coeficientes de autocorrelación
coef_ar1 <- c(0.1, 0.95)
 
# Simulación de los procesos autoregresivos
serie1 <- arima.sim(model = list(ar = coef_ar1[1]), n = n, sd = volatilidad)
serie2 <- arima.sim(model = list(ar = coef_ar1[2]), n = n, sd = volatilidad)
 
# Calcular el promedio de las series
promedio <- mean(c(serie1, serie2))
 
# Crear el gráfico
datos <- data.frame(
  Tiempo = 1:n,
  Serie1 = serie1,
  Serie2 = serie2
)
 
# Graficar las series con ggplot2
ggplot(datos) +
  geom_line(aes(x = Tiempo, y = Serie1, color = "AR(0.1)")) +
  geom_line(aes(x = Tiempo, y = Serie2, color = "AR(0.9)")) +
  geom_hline(yintercept = mean(serie1), linetype = "dashed", color = "gray") +
  geom_hline(yintercept = mean(serie2), linetype = "dashed", color = "black") +
  labs(x = "Tiempo", y = "Valor", title = element_blank()) +
  scale_color_manual(name = "Modelo", values = c("AR(0.1)" = "gray", "AR(0.9)" = "black")) +
  theme_classic() +
  theme(legend.title = element_blank(),
        legend.position = c(0.2,0.8))

 1.       Estimar el coeficiente autoregresivo de una serie o conjunto de series

Una primera medida de persistencia de las series anteriores, se obtiene a partir de coeficientes autoregresivo de primer orden. En el siguiente ejemplo se colocan una estimación vectorizada del mismo. Primero se crea una matriz de datos con serie1 y serie2, para luego usar la función apply para calcular los coeficientes autorregresivos de primer orden para cada columna. Como ha de esperarse, la serie más persistente ha mostrado mayor persistencia.

# AR(1) de una serie temporal
arima(serie1, order = c(1,0,0)) |>
coef()
  ar1  intercept
0.07822495 0.07983069
 
# AR(1) de múltiples series temperoales
datos <- cbind(serie1, serie2)
apply(datos, 2, function(x) coef(arima(x, order = c(1,0,0)))["ar1"])
    serie1     serie2
0.07822495 0.91674843

2.       Obtener una estimación histórica del nivel de persistencia

Para series largas, igual Podemos estudiar la evolución histórica sobre resistencia usando la función rollapply del paquete zoo. Esta función estima una ventana móvil de tamaño width, donde a cada segmento de la muestra se le aplica una función propia (FUN). Si se aplica para la serie.      .

#ar(1) histórico de una serie temporal
library(zoo)
his_ar1 <- function(x) coef(arima(x, order = c(1,0,0)))["ar1"]
ar_t1 <- rollapply(serie1, width=20, FUN=his_ar1)
 
data1 <- data.frame(t = 1:length(ar_t1),
                    arh = ar_t1)
 
ggplot(data1, aes(t,arh)) +
  geom_line() +
  theme_classic()
plot(ar_t1, type="l")

 


En caso de sesear estimar la dinámica de la persistencia histórica de múltiples series a la vez, podemos aplicar la misma lógica de la función apply, anidando rollapply.

 #ar(1) histórico de múltiples series temporales
data_ar <- apply(datos, 2, function(x){rollapply(x, width=20,FUN=his_ar1)})
 
data1 <- data.frame(t = 1:length(ar_t1),
                    data_ar)
 
ggplot(data1, aes(t)) +
  geom_line(aes(t,serie1)) +
  geom_line(aes(t,serie2)) +
  theme_classic()



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 ...