Este documento pone en práctica los conceptos teóricos del Capítulo 7: Análisis de Regresión Múltiple. Utilizaremos los datos del proyecto dq-datasci-gujarati para ilustrar:
La comparación de modelos (\(R^2\) lineal vs log-log) usando la demanda de café.
Regresión Polinomial usando funciones de costos.
Analizaremos la relación entre el consumo de café (\(Y\)) y su precio real (\(X\)). La teoría sugiere una relación inversa, pero ¿qué forma funcional ajusta mejor?
Cargamos los datos desde el archivo local Table7_1.rda.
# Cargar datos del repositorio local
load("../data/Table7_1.rda")
# Preprocesamiento: Renombrar variables y asegurar formato numérico
# Es CRUCIAL convertir de factor a caracter y luego a numérico para evitar errores en log()
df_cafe <- Table7_1 %>%
rename(
Consumo_Y = Y, # Tazas por persona/día
Precio_X = X # Precio $ por libra
) %>%
mutate(
Consumo_Y = as.numeric(as.character(Consumo_Y)),
Precio_X = as.numeric(as.character(Precio_X))
)
# Vista previa
head(df_cafe)
## YEAR Consumo_Y Precio_X
## 1 1970 2.57 0.77
## 2 1971 2.50 0.74
## 3 1972 2.35 0.72
## 4 1973 2.30 0.73
## 5 1974 2.25 0.76
## 6 1975 2.20 0.75
Estimaremos dos modelos rivales:
Modelo Lineal: \(Y_t = \beta_1 + \beta_2 X_t + u_t\)
Modelo Log-Log (Elasticidad Constante): \(\ln Y_t = \alpha_1 + \alpha_2 \ln X_t + u_t\)
# Modelo Lineal
mod_lineal <- lm(Consumo_Y ~ Precio_X, data = df_cafe)
# Modelo Log-Log
mod_loglog <- lm(log(Consumo_Y) ~ log(Precio_X), data = df_cafe)
# Resumen de resultados
stargazer(mod_lineal, mod_loglog, type = "text",
title = "Comparación: Lineal vs Log-Log",
column.labels = c("Lineal", "Log-Log"),
model.numbers = FALSE)
##
## Comparación: Lineal vs Log-Log
## =========================================================
## Dependent variable:
## ----------------------------
## Consumo_Y log(Consumo_Y)
## Lineal Log-Log
## ---------------------------------------------------------
## Precio_X -0.480***
## (0.114)
##
## log(Precio_X) -0.253***
## (0.049)
##
## Constant 2.691*** 0.777***
## (0.122) (0.015)
##
## ---------------------------------------------------------
## Observations 11 11
## R2 0.663 0.745
## Adjusted R2 0.625 0.716
## Residual Std. Error (df = 9) 0.129 0.050
## F Statistic (df = 1; 9) 17.687*** 26.267***
## =========================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
Nota importante: No se pueden comparar directamente los \(R^2\) de estos dos modelos porque la variable dependiente es diferente (\(Y\) vs \(\ln Y\)).
Modelo Lineal: El coeficiente de \(X\) (-0.479) sugiere que si el precio aumenta 1 dólar, el consumo baja casi media taza.
Modelo Log-Log: El coeficiente (-0.253) es la elasticidad precio. Indica que si el precio aumenta un 1%, el consumo baja un 0.25%.
ggplot(df_cafe, aes(x = Precio_X, y = Consumo_Y)) +
geom_point(color = "darkred", size = 3) +
geom_smooth(method = "lm", formula = y ~ x, color = "blue", se = FALSE, aes(linetype = "Lineal")) +
# Para visualizar el ajuste log-log en la escala original, necesitamos transformar
geom_line(aes(y = exp(predict(mod_loglog)), linetype = "Log-Log"), color = "green", size = 1) +
labs(title = "Consumo de Café vs. Precio",
subtitle = "Ajuste Lineal vs. Log-Lineal",
x = "Precio Real ($/lb)",
y = "Tazas por día") +
scale_linetype_manual(name = "Modelo", values = c("Lineal" = "solid", "Log-Log" = "dashed")) +
theme_minimal()
La teoría microeconómica sugiere que la curva de Costo Total (CT) tiene forma de “S”, lo que implica curvas de Costo Marginal y Medio en forma de “U”. Para capturar esto, usamos un polinomio de tercer grado.
\[CT_i = \beta_0 + \beta_1 Q_i + \beta_2 Q_i^2 + \beta_3 Q_i^3 + u_i\]
Cargamos los datos desde Table7_4.rda.
# Cargar datos
load("../data/Table7_4.rda")
# Inspeccionar nombres de columnas para evitar errores
print(names(Table7_4))
## [1] "X" "Y"
# Preprocesamiento: Asegurar nombres descriptivos y conversión numérica
# Intento de renombrado asumiendo nombres comunes si 'y' falla.
# Si el dataset tiene 'Y' en lugar de 'y', esto lo arreglará.
df_costos <- Table7_4
# Normalizamos nombres a minúsculas para evitar problemas de case-sensitivity
names(df_costos) <- tolower(names(df_costos))
df_costos <- df_costos %>%
rename(
Output = x, # Asumiendo que ahora es 'x' minúscula
TotalCost = y # Asumiendo que ahora es 'y' minúscula
) %>%
mutate(
Output = as.numeric(as.character(Output)),
TotalCost = as.numeric(as.character(TotalCost))
)
head(df_costos)
## Output TotalCost
## 1 1 193
## 2 2 226
## 3 3 240
## 4 4 244
## 5 5 257
## 6 6 260
# Creamos términos cuadráticos y cúbicos dentro de la fórmula con I()
mod_cubico <- lm(TotalCost ~ Output + I(Output^2) + I(Output^3), data = df_costos)
summary(mod_cubico)
##
## Call:
## lm(formula = TotalCost ~ Output + I(Output^2) + I(Output^3),
## data = df_costos)
##
## Residuals:
## Min 1Q Median 3Q Max
## -4.4263 -0.7416 0.3744 1.4635 4.4350
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 141.76667 6.37532 22.24 5.41e-07 ***
## Output 63.47766 4.77861 13.28 1.13e-05 ***
## I(Output^2) -12.96154 0.98566 -13.15 1.19e-05 ***
## I(Output^3) 0.93959 0.05911 15.90 3.93e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.285 on 6 degrees of freedom
## Multiple R-squared: 0.9983, Adjusted R-squared: 0.9975
## F-statistic: 1202 on 3 and 6 DF, p-value: 1.001e-08
Según la teoría (Ec. 7.10.5 del libro), para que las curvas de costos tengan sentido económico (forma de U normal):
\(\beta_0, \beta_1 > 0\)
\(\beta_2 < 0\)
\(\beta_3 > 0\)
Observemos nuestros coeficientes:
coef(mod_cubico)
## (Intercept) Output I(Output^2) I(Output^3)
## 141.7666667 63.4776612 -12.9615385 0.9395882
Intercepto (\(\beta_0\)): Positivo (Costo Fijo)
Output (\(\beta_1\)): Positivo
Output^2 (\(\beta_2\)): Negativo (ley rendimientos marginales crecientes iniciales)
Output^3 (\(\beta_3\)): Positivo (ley rendimientos marginales decrecientes posteriores)
Conclusión: Los signos coinciden perfectamente con la teoría económica.
ggplot(df_costos, aes(x = Output, y = TotalCost)) +
geom_point(size = 3) +
stat_smooth(method = "lm", formula = y ~ x + I(x^2) + I(x^3), color = "red") +
labs(title = "Función de Costos Totales",
subtitle = "Ajuste Polinomial Cúbico",
x = "Nivel de Producción (Output)",
y = "Costo Total ($)") +
theme_minimal()
Conclusión General
El análisis de regresión múltiple nos permite modelar relaciones complejas:
A través de transformaciones logarítmicas obtenemos elasticidades constantes.
A través de polinomios modelamos cambios en la curvatura (costos marginales).
El \(R^2\) ajustado debe usarse siempre que comparemos modelos con diferente número de variables independientes.