3 may 2025

Recodificación de Variables en R

 La recodificación de variables es una tarea esencial en el análisis de datos que nos permite transformar datos continuos en categorías más interpretables, facilitando tanto el análisis como la visualización. En este artículo, exploraremos diferentes técnicas para recodificar variables utilizando el poderoso ecosistema tidyverse en R.

 1.     Preparación del entorno

 Primero, cargamos las librerías necesarias y el conjunto de datos con el que trabajaremos:

 # Cargamos las librerías necesarias para manipulación de datos
library(tidyselect)  # Para selección avanzada de variables
library(wooldridge)  # Paquete con datos de ejemplos econométricos
 
# Cargamos el dataset wage1 (datos sobre salarios)
data("wage1")
 
# Visualizamos los datos
wage1 |> View()

El conjunto de datos wage1 contiene información sobre salarios, educación, experiencia laboral y otras variables socioeconómicas. Antes de cualquier recodificación, resulta útil explorar la relación entre las variables existentes.

2.     Exploración visual previa

Primero, examinemos la relación entre los años de educación (educ), el logaritmo del salario (lwage) y el género (female) (es siempre muy importante estudiar las relaciones y las características de las variables):

 # Visualizamos la relación entre educación y salario por género
wage1 |>
  # dplyr::filter(educ<=5) |> 
  ggplot(aes(x=educ, y=lwage, color=factor(female))) +
  geom_point() +
  geom_jitter(width = 0.4, height = 0, alpha = 0.6) + 
  geom_smooth(method = "lm") 

Este gráfico nos muestra cómo el logaritmo del salario tiende a aumentar con los años de educación, y cómo esta relación varía según el género. La función geom_jitter() añade una pequeña dispersión horizontal para evitar la superposición de puntos, mejorando la visualización.

3.     Recodificación Categórica con case_when()

La primera estrategia que exploraremos utiliza la función case_when() para crear categorías educativas basadas en rangos de años de estudio:

# Opción 1: Recodificación arbitraria basada en niveles educativos estándar
wage1 <- wage1 |>
  mutate(rango_Educ = case_when(
    educ == 0 ~ "0 esco",                # Sin escolaridad
    educ >= 1 & educ <= 6 ~ "Primaria",  # Educación primaria (1-6 años)
    educ >= 7 & educ <= 12 ~ "aSecundaria", # Educación secundaria (7-12 a)
    educ >= 13 ~ "Terciaria"             # Educación superior (13+ años)
  ),
  # Convertimos a factor con orden específico
  rango_Educ = factor(rango_Educ, levels = c("0 esco", "Primaria", "aSecundaria", "Terciaria"))
  )

Esta recodificación utiliza case_when() para crear categorías educativas significativas. La función evalúa cada condición secuencialmente y asigna la categoría correspondiente. Luego, convertimos la nueva variable en un factor ordenado para mantener la jerarquía natural de los niveles educativos.

Visualicemos cómo se relacionan estos rangos educativos con el salario:

# Visualizamos la mediante boxplots
wage1 |>
  ggplot(aes(x=rango_Educ, y=wage)) +
  geom_boxplot()

Los diagramas de caja nos permiten comparar la distribución salarial entre los diferentes niveles educativos, mostrando la mediana, los cuartiles y los valores atípicos para cada grupo.

 4.     Recodificación por Cuantiles con ntile()

Una alternativa a la categorización arbitraria es dividir los datos en cuantiles utilizando la función ntile(): 

# Opción 2: Recodificación basada en quintiles (divide los datos en 5 grupos de igual tamaño)
wage1 <- wage1 |>
  mutate(rango_Educ2 = ntile(educ, 5)) 

Esta técnica divide la variable educ en cinco grupos con aproximadamente el mismo número de observaciones en cada uno. Es especialmente útil cuando buscamos crear grupos balanceados sin imponer puntos de corte arbitrarios.

Visualicemos esta nueva categorización:

# Visualizamos la relación entre quintiles educativos y salario
wage1 |>
  ggplot(aes(x=factor(rango_Educ2), y=wage)) +
  geom_boxplot()

Finalmente, calculemos algunas estadísticas por grupo para evaluar las diferencias entre los quintiles educativos:

# Calculamos estadísticas descriptivas por quintil educativo
wage1 |>
  group_by(rango_Educ2) |>
  summarise(obs = n(),                           # Número de observaciones
            meand_educ = mean(wage, na.rm=T),    # Salario medio
            vol_educ = meand_educ/sd(wage, na.rm=T))   

Este análisis nos proporciona el número de observaciones, el salario medio y una medida de volatilidad relativa para cada quintil educativo.

5.     Recodificación con intervalos específicos usando cut()

La función cut() nos permite dividir una variable numérica en intervalos específicos, ofreciendo mayor control sobre los puntos de corte:

# Opción 3: Recodificación con intervalos específicos usando cut()
wage1 <- wage1 |>
  mutate(rango_Educ3 = cut(educ,
               breaks = c(0, 6, 12, 16, Inf),  # Puntos de corte específicos
               labels = c("Básica", "Media", "Universitaria", "Posgrado"),
       include.lowest = TRUE,  # Incluye el valor mínimo
                right = FALSE))  # Intervalos cerrados a la izquierda
 
# Visualizamos la nueva categorización
wage1 |>
  ggplot(aes(x=rango_Educ3, y=wage)) +
  geom_boxplot() +
  labs(title = "Distribución de salarios por nivel educativo",
       x = "Nivel educativo",
       y = "Salario por hora ($)")

Esta técnica nos permite definir manualmente los límites de cada categoría, lo que es ideal cuando tenemos umbrales específicos basados en conocimiento del dominio (como los niveles educativos estándar). El parámetro include.lowest = TRUE asegura que el valor mínimo (0 en este caso) se incluya en el primer intervalo, mientras que right = FALSE define intervalos cerrados a la izquierda.

 6.     Creación de variables dummy con if_else()

Para análisis estadísticos como regresiones, a menudo necesitamos variables binarias (0/1):

# Opción 4: Creación de variables dummy utilizando if_else()
wage1 <- wage1 |>
  mutate(
    # Educación superior (binaria)
    educ_superior = if_else(educ >= 13, 1, 0),
   
    # Alta experiencia (binaria)
    exper_alta = if_else(exper > median(exper), 1, 0),
   
    # Interacción entre educación superior y género
    educ_sup_mujer = educ_superior * female
  )
 
# Visualizamos el efecto de la educación superior en el salario por género
wage1 |>
  ggplot(aes(x = factor(educ_superior), y = wage, fill = factor(female))) +
  geom_boxplot() +
  labs(title = "Efecto de educación superior en salarios por género",
       x = "Educación superior",
       y = "Salario por hora ($)",
       fill = "Mujer")

La función if_else() es perfecta para crear variables binarias, ya que evalúa una condición y asigna un valor para los casos verdaderos y otro para los falsos. En este ejemplo, creamos indicadores para educación superior, alta experiencia, y una interacción entre educación superior y género.

 7.     Normalización para análisis de desviaciones estándar

 La normalización nos permite expresar los valores en términos de cuántas desviaciones estándar se alejan de la media:

 # Opción 5: Normalización de variables para análisis de desviaciones estándar
wage1 <- wage1 |>
  mutate(
    # Z-score de educación (normalización)
    educ_z = (educ - mean(educ)) / sd(educ),
   
    # Z-score de experiencia
    exper_z = (exper - mean(exper)) / sd(exper),
   
    # Z-score de salario
    wage_z = (wage - mean(wage)) / sd(wage)
  )
 
# Visualizamos distribución de valores normalizados
wage1 |>
  select(educ_z, exper_z, wage_z) |>
  pivot_longer(cols = everything(), names_to = "variable", values_to = "valor_z") |>
  ggplot(aes(x = valor_z, fill = variable)) +
  geom_density(alpha = 0.5) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  labs(title = "Distribución de variables normalizadas",
       x = "Desviaciones estándar desde la media",
       y = "Densidad")

La normalización (cálculo de z-scores) convierte los valores a una escala común donde 0 representa la media y cada unidad representa una desviación estándar. Esto facilita la comparación de variables con diferentes unidades o escalas, y es especialmente útil para identificar valores atípicos y para ciertos modelos estadísticos.

3 abr 2025

Análisis de eventos en R: Dow Jones Industrial Average (DJIA) durante diferentes administraciones presidenciales de USA

El siguiente ejemplo en R muestra como realizar un análisis comparativo del Dow Jones Industrial Average (DJIA) durante diferentes administraciones presidenciales de USA. Este código te permitirá realizar el estudio de eventos que deseas sobre el comportamiento del DJIA durante los diferentes periodos presidenciales. Puntualmente, se normalizan las series, en relación a una fecha inicial, para describir o comparar la dinámica de las mismas. 

 1.       Descarga datos

En primer lugar se cargan los datos desde FRED (https://fred.stlouisfed.org/series/DJIA). El código utiliza read_excel para cargar los datos directamente desde tu ruta específica, con el nombre de la hoja "Daily, Close". es decir, el Excel descargado debe estar en el directorio.

 # Cargar las bibliotecas necesarias
library(readxl)
library(ggplot2)
library(dplyr)
library(lubridate)
library(zoo)
 
DJIA <- read_excel("//… /DJIA.xlsx",
                  sheet = "Daily, Close", col_types = c("date", "numeric"))
#View(DJIA)
 
# Renombrar columnas para mayor claridad (opcional)
names(DJIA) <- c("Fecha", "Valor")
 
DJIA |>
  na.omit()

Maneja la estructura de datos donde las columnas son observation_date y DJIA, renombrándolas a "Fecha" y "Valor" para mayor claridad.

# A tibble: 2,608 × 2
   Fecha       Valor
   <date>      <dbl>
 1 2015-04-06 17881.
 2 2015-04-07 17875.
 3 2015-04-08 17903.
 4 2015-04-09 17959.
 5 2015-04-10 18058.
 6 2015-04-13 17977.
 7 2015-04-14 18037.
 8 2015-04-15 18113.
 9 2015-04-16 18106.
10 2015-04-17 17826.
# 2,598 more rows
# Use `print(n = ...)` to see more rows

2.       Normalización: Para cada administración (Obama 1, Obama 2, Trump 1, Biden, Trump 2), el código normaliza el índice tomando como base 100 el primer día de cada gobierno.

El código sigue realizando la normalización de las series, tomando como base 100 el primer día disponible de cada administración presidencial. Busca la fecha igual al inicio o la fecha próxima disponible próximo al evento, para evitar valores en blanco cuando no se tengan valores para la fecha del día de incio.

 # Establecer fechas para cada administración presidencial
# Obama 1: 20 de enero de 2009
# Obama 2: 20 de enero de 2013
# Trump 1: 20 de enero de 2017
# Biden: 20 de enero de 2021
# Trump 2: 20 de enero de 2025
 
# Asegurarse que Fecha es tipo Date
DJIA$Fecha <- as.Date(DJIA$Fecha)
 
# Ver el rango de fechas disponibles
fecha_min <- min(DJIA$Fecha)
fecha_max <- max(DJIA$Fecha)
cat("Rango de fechas disponibles:", as.character(fecha_min), "a", as.character(fecha_max), "\n")
 
# Establecer fechas para cada administración presidencial
administraciones <- data.frame(
  Nombre = c("Trump 1", "Biden", "Trump 2"),
  Fecha_Oficial = as.Date(c("2017-01-20", "2021-01-20", "2025-01-20")),
  stringsAsFactors = FALSE
)

# Encontrar la primera fecha disponible después de la fecha oficial para cada administración
for (i in 1:nrow(administraciones)) {
  fecha_oficial <- administraciones$Fecha_Oficial[i]
  primera_fecha_disponible <- min(DJIA$Fecha[DJIA$Fecha >= fecha_oficial], na.rm = TRUE)
 
  # Solo considerar administraciones que tienen datos dentro del rango
  if (primera_fecha_disponible <= fecha_max) {
    administraciones$Fecha_Inicio[i] <- primera_fecha_disponible
  } else {
    administraciones$Fecha_Inicio[i] <- NA
  }
}
# Eliminar administraciones sin datos disponibles
administraciones <- administraciones[!is.na(administraciones$Fecha_Inicio),]
 
# Imprimir fechas de inicio reales utilizadas
cat("Fechas de inicio utilizadas para cada administración:\n")
for (i in 1:nrow(administraciones)) {
  cat(administraciones$Nombre[i], ": Fecha oficial =",
      as.character(administraciones$Fecha_Oficial[i]),
      ", Fecha utilizada =",
      as.character(administraciones$Fecha_Inicio[i]), "\n")
}
 
# Añadir fechas de fin (último día de la administración o fecha más reciente disponible)
for (i in 1:nrow(administraciones)) {
  if (i < nrow(administraciones)) {
    # Último día antes de la siguiente administración
    administraciones$Fecha_Fin[i] <- administraciones$Fecha_Inicio[i+1] - 1
  } else {
    # Para la última administración, usar la fecha más reciente disponible
    administraciones$Fecha_Fin[i] <- fecha_max
  }
}
 
# Función para normalizar por administración
normalizar_por_administracion <- function(df, admin_row) {
  nombre <- admin_row$Nombre
  fecha_inicio <- admin_row$Fecha_Inicio
  fecha_fin <- admin_row$Fecha_Fin
 
  # Filtrar por período
  periodo <- df %>%
    filter(Fecha >= fecha_inicio & Fecha <= fecha_fin)
 
  # Si no hay datos para este período, retornar NULL
  if(nrow(periodo) == 0) {
    return(NULL)
  }
 
  # Normalizar al primer día disponible
  primer_valor <- periodo$Valor[1]
  periodo$Valor_Normalizado <- periodo$Valor / primer_valor * 100
 
  # Añadir información de administración y días transcurridos
  periodo$Administracion <- nombre
  periodo$Dias <- as.numeric(periodo$Fecha - fecha_inicio)
 
  return(periodo)
}
 
# Aplicar normalización para cada administración
resultados <- list()
 
for(i in 1:nrow(administraciones)) {
  temp <- normalizar_por_administracion(DJIA, administraciones[i,])
 
  if(!is.null(temp)) {
    resultados[[i]] <- temp
  }
}
 
# Combinar resultados
datos_normalizados <- bind_rows(resultados)
 
# Definir colores para cada administración - paleta sobria para paper económico
colores_admin <- c("Obama 2" = "steelblue", "Trump 1" = "#F5ABB2", "Biden" = "#89ACC2", "Trump 2" = "#732F37")

3.       Visualización: Crea un gráfico de líneas donde puedes ver el rendimiento relativo del DJIA a lo largo del tiempo para cada administración, lo que facilita la comparación entre ellas.

# Crear gráfico
ggplot(datos_normalizados, aes(x = Dias, y = Valor_Normalizado, color = Administracion)) +
  geom_line(size = 0.8) +
  scale_color_manual(values = colores_admin) +
  labs(
    title = "Rendimiento relativo del DJIA por administración presidencial",
    subtitle = "Índice relativo al primer día de cada administración (100 = primer día)",
    x = "Días desde inicio de administración",
    y = "DJIA (Normalizado, Primer día = 100)",
    color = "Administración"
  ) +
  theme_bw() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "gray90"),
    legend.position = "bottom",
    legend.title = element_text(face = "plain", size = 10),
    legend.text = element_text(size = 9),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 11),
    plot.subtitle = element_text(hjust = 0.5, size = 10, face = "italic"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 9)
  ) +
  scale_x_continuous(breaks = seq(0, 1500, 365), labels = function(x) paste0(round(x/365, 1), " años")) +
  scale_y_continuous(breaks = seq(80, 180, 20))



Recodificación de Variables en R

  La recodificación de variables es una tarea esencial en el análisis de datos que nos permite transformar datos continuos en categorías más...