0.1 Con Mi Profe: Julio Hurtado Marquez; EMAIL_TAREAS:


1 📊 PRUEBAS DE HIPÓTESIS - GUÍA COMPLETA

📊 PRUEBAS DE HIPÓTESIS

Fundamentos, tipos de pruebas, verificación de normalidad y aplicaciones prácticas con R y Python



2 INTRODUCCIÓN A LAS PRUEBAS DE HIPÓTESIS

📝 DEFINICIÓN

Una prueba de hipótesis es un procedimiento estadístico que permite evaluar si la información muestral es compatible o no con una afirmación sobre un parámetro poblacional.

Una hipótesis estadística es una afirmación (supuesto) sobre un parámetro como:

  • la media poblacional \(μ\)
  • la proporción poblacional \(p\)
  • la diferencia de medias \(μ₁ - μ₂\)
  • la diferencia de proporciones \(p₁ - p₂\)
  • la varianza poblacional \(\sigma^2\)
  • el cociente de varianzas \(\dfrac{\sigma_1^2}{\sigma_2^2}\)

Con los datos de la muestra intentamos decidir si la evidencia empírica es compatible con una afirmación sobre la población.


2.1 Tipos de Hipótesis

En toda prueba planteamos dos hipótesis complementarias:

Hipótesis Símbolo Significado
Hipótesis Nula H₀ “No hay diferencia”, “No hay efecto”, “Todo sigue igual”
Hipótesis Alternativa H₁ o Hₐ “Sí hay diferencia”, “Sí cambió”, “Sí hay efecto”

2.1.1 Hipótesis Nula (H₀)

Es la afirmación “neutral”, de no diferencia, no cambio o situación “normal”.

Ejemplos:

  • H₀: μ = 500,000 (La media es 500,000)
  • H₀: μ₁ = μ₂ (Las medias de las dos muestras son iguales)
  • H₀: p = 0.30 (La proporción es 0.30)

2.1.2 Hipótesis Alternativa (H₁)

Es la afirmación que quieres evidenciar: sí hay cambio, sí hay diferencia, sí hay efecto.

Tipos de pruebas:

Tipo H₀ H₁ Significado
Bilateral μ = 500,000 μ ≠ 500,000 La media es distinta (puede ser mayor o menor)
Unilateral derecha μ₁ ≤ μ₂ μ₁ > μ₂ El grupo 1 tiene una media mayor que el grupo 2
Unilateral izquierda p ≥ 0.30 p < 0.30 La proporción es menor que 0.30

2.2 Nivel de Significancia (α)

El nivel de significancia es la probabilidad de rechazar H₀ siendo H₀ verdadera:

α = P(rechazar H₀ | H₀ es verdadera)

Es un riesgo que decides aceptar antes del estudio (riesgo de “falso positivo”).

Valores típicos:

  • α = 0.05: aceptas un 5% de probabilidad de equivocarte
  • α = 0.01: aceptas un 1% de probabilidad de equivocarte

2.3 Valor p (p-value)

El p-valor es la probabilidad de obtener un resultado igual o más extremo que el observado, asumiendo que H₀ es cierta.

Regla de decisión:

  • Si p ≤ α: la evidencia contra H₀ es fuerte → se rechaza H₀
  • Si p > α: la evidencia contra H₀ es débil → no se rechaza H₀

3 ¿SE PUEDE HACER PRUEBA DE HIPÓTESIS SI TENGO TODA LA POBLACIÓN?

Si tu “muestra” es en realidad toda la población, no tiene sentido aplicar pruebas de hipótesis (ni intervalos de confianza).

¿Por qué? Porque si ya observaste a toda la población:

  • No hay incertidumbre debida al muestreo
  • El parámetro poblacional es conocido exactamente
  • El error estándar asociado al muestreo es, conceptualmente, cero

Excepción útil: Si quieres usar los datos censales de 2024 para inferir sobre estudiantes futuros (2025, 2026…), puedes tratar el año 2024 como una “muestra” de una población conceptual más amplia.


4 ESQUEMA GENERAL DE UNA PRUEBA DE HIPÓTESIS

Pasos a seguir:

  1. Plantear las hipótesis H₀ y H₁ (problema)
  2. Verificar si los datos presentan una distribución normal
  3. Seleccionar la prueba adecuada
  4. Calcular el estadístico de prueba
  5. Obtener el p-valor
  6. Analizar y concluir:
    • Si p ≤ α: Rechazar H₀
    • Si p > α: No rechazar H₀
  7. Inferir sobre la población a partir de los datos

5 VERIFICACIÓN DE NORMALIDAD

Antes de decidir el tipo de prueba (paramétrica o no paramétrica), se debe evaluar la normalidad de los datos.

Normalidad Tipo de prueba
Paramétrica
No No paramétrica

5.1 Gráfico Q-Q plot

Interpretación: Si los puntos del Q-Q plot se alinean aproximadamente en una línea diagonal, se considera que los datos son aproximadamente normales.

Código en R:

##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   149.2   165.6   170.6   170.8   176.2   189.7
## [1] 8.215343

Código en Python:

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats

# Datos simulados
np.random.seed(123)
altura_personas = np.random.normal(170, 9, 100)

# Resumen estadístico
print(f"Media: {np.mean(altura_personas):.2f}")
print(f"Desviación estándar: {np.std(altura_personas):.2f}")

# Gráfico Q-Q plot
stats.probplot(altura_personas, dist="norm", plot=plt)
plt.title("Q-Q plot para altura de personas")
plt.show()

5.2 Prueba de Shapiro-Wilk

Hipótesis: - H₀: Los datos provienen de una distribución normal - H₁: Los datos no provienen de una distribución normal

Código en R:

## 
##  Shapiro-Wilk normality test
## 
## data:  altura_personas
## W = 0.99388, p-value = 0.9349

Código en Python:

# Prueba de Shapiro-Wilk
shapiro_stat, shapiro_p = stats.shapiro(altura_personas)
print(f"Estadístico W: {shapiro_stat:.5f}")
print(f"p-valor: {shapiro_p:.4f}")

Interpretación: Con α = 0.05, como p = 0.9349 > 0.05, NO rechazamos H₀. Los datos son compatibles con la normalidad.

5.3 Prueba de Kolmogorov-Smirnov

Código en R:

## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  altura_personas
## D = 0.058097, p-value = 0.8884
## alternative hypothesis: two-sided

Código en Python:

# Prueba de Kolmogorov-Smirnov
ks_stat, ks_p = stats.kstest(altura_personas, 'norm', args=(np.mean(altura_personas), np.std(altura_personas)))
print(f"Estadístico D: {ks_stat:.6f}")
print(f"p-valor: {ks_p:.4f}")

Interpretación: p-valor grande (>0.05) indica que no hay evidencia fuerte contra la normalidad.

5.4 Métodos para evaluar normalidad

Método Definición ¿Cuándo usarla?
Histograma + curva normal Compara visualmente la distribución con una curva normal Primer vistazo obligatorio
Gráfico Q-Q plot Compara cuantiles teóricos con observados Siempre recomendable
Shapiro-Wilk Prueba estadística de normalidad Muestras pequeñas o medianas (n ≲ 5000)
Kolmogorov-Smirnov Compara distribución empírica con teórica Prueba general de bondad de ajuste
Anderson-Darling Da más peso a las colas Cuando se sospecha que las colas no son normales

6 SELECCIÓN DE LA PRUEBA ADECUADA

Normalidad / supuestos Tipo de prueba recomendada
Normalidad razonable y varianzas aproximadamente homogéneas, sin outliers extremos Paramétrica
Normalidad razonable pero varianzas muy distintas o muchos outliers Paramétrica robusta (Welch, transformaciones) o No paramétrica
No No paramétrica

7 PRUEBAS PARAMÉTRICAS

7.1 Prueba t de Student (una muestra)

Definición: Compara la media muestral con una media poblacional (μ₀).

Fórmula: \[t = \frac{\bar{x} - \mu_0}{s / \sqrt{n}}\]

Código en R:

t.test(x, mu = 50)

Código en Python:

from scipy import stats
stats.ttest_1samp(x, 50)

7.2 Prueba t de Student (dos muestras independientes)

Definición: Compara medias entre dos grupos independientes.

Fórmula (versión de Welch): \[t = \frac{\bar{x}_1 - \bar{x}_2}{\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}}}\]

Código en R:

t.test(x ~ grupo, var.equal = FALSE)  # Welch
t.test(x ~ grupo, var.equal = TRUE)   # varianzas iguales

Código en Python:

stats.ttest_ind(x1, x2, equal_var=False)  # Welch
stats.ttest_ind(x1, x2, equal_var=True)   # varianzas iguales

Ejemplo completo en R:

# Datos
calificaciones_metodo_A <- c(85, 88, 90, 87, 92, 89, 91, 86, 93, 88)
calificaciones_metodo_B <- c(78, 82, 80, 79, 81, 83, 77, 84, 80, 82)

# Prueba de normalidad
shapiro.test(calificaciones_metodo_A)  # p = 0.9347
shapiro.test(calificaciones_metodo_B)  # p = 0.8777

# Prueba t de Welch
t.test(calificaciones_metodo_A, calificaciones_metodo_B)
# t = 5.741, df = 17.856, p-value = 1.984e-05
## 
##  Shapiro-Wilk normality test
## 
## data:  calificaciones_metodo_A
## W = 0.97523, p-value = 0.9347
## 
##  Shapiro-Wilk normality test
## 
## data:  calificaciones_metodo_B
## W = 0.97798, p-value = 0.9535
## 
##  Welch Two Sample t-test
## 
## data:  calificaciones_metodo_A and calificaciones_metodo_B
## t = 7.6734, df = 17.569, p-value = 5.173e-07
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##   6.023499 10.576501
## sample estimates:
## mean of x mean of y 
##      88.9      80.6

Ejemplo completo en Python:

import numpy as np
from scipy import stats

calificaciones_A = np.array([85, 88, 90, 87, 92, 89, 91, 86, 93, 88])
calificaciones_B = np.array([78, 82, 80, 79, 81, 83, 77, 84, 80, 82])

# Prueba de normalidad
_, p_A = stats.shapiro(calificaciones_A)
_, p_B = stats.shapiro(calificaciones_B)
print(f"Shapiro-Wilk A: p = {p_A:.4f}")
print(f"Shapiro-Wilk B: p = {p_B:.4f}")

# Prueba t de Welch
t_stat, p_valor = stats.ttest_ind(calificaciones_A, calificaciones_B, equal_var=False)
print(f"t = {t_stat:.3f}, p = {p_valor:.6e}")

Interpretación: p-valor muy pequeño (1.98e-05) ⇒ se rechaza H₀. Hay una diferencia significativa en las calificaciones medias entre los dos métodos.

7.3 Prueba t pareada

Definición: Compara dos mediciones relacionadas (antes/después) en los mismos sujetos.

Fórmula: \[t = \frac{\bar{d}}{s_d / \sqrt{n}}\]

Código en R:

t.test(antes, despues, paired = TRUE)

Código en Python:

stats.ttest_rel(antes, despues)

7.4 ANOVA de un factor

Definición: Compara la media entre más de dos grupos independientes.

Hipótesis: - H₀: μ₁ = μ₂ = … = μₖ - H₁: al menos una media es diferente

Modelo: Yᵢⱼ = μ + αᵢ + εᵢⱼ

Estadístico F: \[F = \frac{MS_{entre}}{MS_{dentro}} = \frac{SC_{entre}/(k-1)}{SC_{dentro}/(N-k)}\]

Código en R:

modelo <- aov(y ~ grupo, data = datos)
summary(modelo)

Código en Python:

import statsmodels.api as sm
from statsmodels.formula.api import ols

modelo = ols('y ~ C(grupo)', data=datos).fit()
anova_table = sm.stats.anova_lm(modelo, typ=2)
print(anova_table)

Ejemplo en R:

set.seed(123)
datos_anova <- data.frame(
  Calificacion = c(rnorm(30, 75, 10), rnorm(30, 80, 10), rnorm(30, 85, 10)),
  Metodo = factor(rep(c("A", "B", "C"), each = 30))
)
modelo <- aov(Calificacion ~ Metodo, data = datos_anova)
summary(modelo)
#             Df Sum Sq Mean Sq F value Pr(>F)  
# Metodo       2    869   434.5   4.523 0.0135 *
# Residuals   87   8358    96.1                 
##             Df Sum Sq Mean Sq F value   Pr(>F)    
## Metodo       2   1794   897.1   11.14 4.94e-05 ***
## Residuals   87   7008    80.5                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

7.5 Correlación de Pearson

Definición: Mide la fuerza de la relación lineal entre dos variables continuas.

Fórmula: \[r = \frac{\sum_{i=1}^{n} (X_i - \bar{X})(Y_i - \bar{Y})}{\sqrt{\sum_{i=1}^{n} (X_i - \bar{X})^2} \sqrt{\sum_{i=1}^{n} (Y_i - \bar{Y})^2}}\]

Código en R:

cor.test(x, y, method = "pearson")

Código en Python:

r, p_valor = stats.pearsonr(x, y)

Ejemplo en R:

set.seed(123)
datos_pearson <- data.frame(
  HorasEstudio = rnorm(50, 25, 5),
  Calificaciones = rnorm(50, 20, 4)
)
cor.test(datos_pearson$HorasEstudio, datos_pearson$Calificaciones)
# t = 13.929, df = 48, p-value < 2.2e-16, cor = 0.895

Ejemplo en R:

## 
##  Pearson's product-moment correlation
## 
## data:  datos_pearson$HorasEstudio and datos_pearson$Calificaciones
## t = -0.24867, df = 48, p-value = 0.8047
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.3111113  0.2449233
## sample estimates:
##         cor 
## -0.03586983

7.6 Regresión Lineal Simple

Modelo: Y = β₀ + β₁X + ε, ε ~ N(0, σ²)

Hipótesis sobre la pendiente: - H₀: β₁ = 0 - H₁: β₁ ≠ 0

Código en R:

modelo_lm <- lm(y ~ x, data = datos)
summary(modelo_lm)

Código en Python:

import statsmodels.api as sm
X = sm.add_constant(x)
modelo = sm.OLS(y, X).fit()
print(modelo.summary())

7.7 Prueba z para una proporción

Definición: Compara una proporción muestral (p̂) con una proporción poblacional (p₀) (muestra grande).

Fórmula: \[z = \frac{\hat{p} - p_0}{\sqrt{\frac{p_0(1-p_0)}{n}}}\]

Código en R:

prop.test(x, n, p = p0, correct = FALSE)

Código en Python:

from statsmodels.stats.proportion import proportions_ztest
stat, p_valor = proportions_ztest(x, n, value=p0)

7.8 Prueba z para dos proporciones

Definición: Compara proporciones de dos grupos independientes (muestras grandes).

Fórmula: \[z = \frac{\hat{p}_1 - \hat{p}_2}{\sqrt{\hat{p}(1-\hat{p})\left(\frac{1}{n_1} + \frac{1}{n_2}\right)}}\]

Código en R:

prop.test(c(x1, x2), c(n1, n2), correct = FALSE)

Código en Python:

stat, p_valor = proportions_ztest([x1, x2], [n1, n2])

7.9 Prueba F para comparar dos varianzas

Definición: Compara si las varianzas de dos poblaciones normales pueden considerarse iguales.

Fórmula: \[F = \frac{s_1^2}{s_2^2}\]

Código en R:

var.test(x1, x2)

Código en Python:

f_stat = np.var(x1, ddof=1) / np.var(x2, ddof=1)
p_valor = 2 * min(1 - stats.f.cdf(f_stat, n1-1, n2-1), stats.f.cdf(f_stat, n1-1, n2-1))

8 PRUEBAS NO PARAMÉTRICAS

8.1 Prueba de signo (una muestra / pareada)

Definición: Contrasta si la mediana de una población es igual a un valor (θ₀) o si la mediana de las diferencias es 0. Solo usa el signo de las diferencias.

Código en R:

library(DescTools)
SignTest(x, mu = theta0)               # una muestra
SignTest(antes - despues, mu = 0)      # pareada

8.2 Wilcoxon (una muestra, rangos con signo)

Definición: Contrasta si la mediana de una población es igual a un valor (θ₀), usando rangos (más potente que la prueba de signo).

Código en R:

wilcox.test(x, mu = theta0, exact = TRUE)

Código en Python:

stat, p_valor = stats.wilcoxon(x - theta0)

8.3 Wilcoxon pareado (rangos con signo)

Definición: Compara dos mediciones relacionadas sin asumir normalidad. Equivalente no paramétrico del t pareado.

Código en R:

wilcox.test(antes, despues, paired = TRUE)

Código en Python:

stat, p_valor = stats.wilcoxon(antes, despues)

8.4 Mann-Whitney / Wilcoxon de rangos (dos muestras independientes)

Definición: Compara dos grupos independientes sin asumir normalidad. Equivalente no paramétrico de la t de Student.

Estadístico U: \[U = n_1 n_2 + \frac{n_1(n_1+1)}{2} - R_1\]

Código en R:

wilcox.test(y ~ grupo, exact = FALSE)

Código en Python:

u_stat, p_valor = stats.mannwhitneyu(x1, x2)

Ejemplo en R:

wilcox.test(Calificaciones ~ Grupo, data = datos)
# W = 268, p-value = 0.00665

8.5 Kruskal-Wallis

Definición: Equivalente no paramétrico del ANOVA de un factor. Compara k grupos independientes usando rangos.

Estadístico H: \[H = \frac{12}{N(N+1)} \sum_{j=1}^{k} \frac{R_j^2}{n_j} - 3(N+1)\]

Código en R:

kruskal.test(y ~ grupo, data = datos)

Código en Python:

h_stat, p_valor = stats.kruskal(*grupos)

Ejemplo en R:

kruskal.test(Calificaciones ~ Grupo, data = datos)
# Kruskal-Wallis chi-squared = 7.8788, df = 2, p-value = 0.01946

8.6 Friedman

Definición: ANOVA no paramétrico para medidas repetidas (diseños en bloques). Compara tratamientos cuando los mismos sujetos reciben todos los tratamientos.

Código en R:

friedman.test(y ~ tratamiento | sujeto, data = datos)

Código en Python:

from scipy.stats import friedmanchisquare
stat, p_valor = friedmanchisquare(*tratamientos)

8.7 Correlación de Spearman (ρₛ)

Definición: Mide la asociación monótona entre dos variables usando rangos. No requiere normalidad.

Fórmula: \[\rho_s = 1 - \frac{6 \sum d_i^2}{n(n^2 - 1)}\]

Código en R:

cor.test(x, y, method = "spearman")

Código en Python:

rho, p_valor = stats.spearmanr(x, y)

8.8 Correlación de Kendall (τ)

Definición: Mide asociación ordinal basándose en pares concordantes y discordantes. Más robusta en muestras pequeñas.

Fórmula: \[\tau = \frac{C - D}{C + D}\]

Código en R:

cor.test(x, y, method = "kendall")

Código en Python:

tau, p_valor = stats.kendalltau(x, y)

8.9 Chi-cuadrado de bondad de ajuste

Definición: Compara frecuencias observadas en categorías con frecuencias esperadas bajo una distribución teórica.

Fórmula: \[\chi^2 = \sum_{i=1}^{k} \frac{(O_i - E_i)^2}{E_i}\]

Código en R:

chisq.test(observadas, p = probs_esperadas)

Código en Python:

chi2, p_valor = stats.chisquare(observadas, f_exp=esperadas)

8.10 Chi-cuadrado de independencia / homogeneidad

Definición: Evalúa si dos variables categóricas son independientes (una población) o si varias poblaciones tienen la misma distribución (homogeneidad).

Fórmula: \[\chi^2 = \sum_{i=1}^{r} \sum_{j=1}^{c} \frac{(O_{ij} - E_{ij})^2}{E_{ij}}, \quad E_{ij} = \frac{(\text{total fila } i)(\text{total columna } j)}{\text{total general}}\]

Código en R:

tabla <- table(x, y)
chisq.test(tabla)

Código en Python:

tabla = pd.crosstab(x, y)
chi2, p_valor, dof, expected = stats.chi2_contingency(tabla)

Ejemplo en R:

tabla_contingencia <- matrix(c(16, 17, 17, 17, 16, 17, 17, 17, 16), nrow=3, byrow=TRUE)
chisq.test(tabla_contingencia)
# X-squared = 0.12, df = 4, p-value = 0.9983

8.11 Prueba exacta de Fisher (tabla 2×2)

Definición: Evalúa asociación entre dos variables dicotómicas cuando los tamaños muestrales son pequeños o los Eᵢⱼ < 5. Usa la distribución hipergeométrica exacta.

Probabilidad de la tabla: \[P(\text{tabla}) = \frac{\binom{a+b}{a}\binom{c+d}{c}}{\binom{n}{a+c}}\]

Código en R:

fisher.test(tabla_2x2)

Código en Python:

odds_ratio, p_valor = stats.fisher_exact(tabla)

Ejemplo en R:

tabla_2x2 <- matrix(c(10, 20, 15, 5), nrow=2, byrow=TRUE)
fisher.test(tabla_2x2)
# p-value = 0.008579

9 CORRESPONDENCIA ENTRE PRUEBAS PARAMÉTRICAS Y NO PARAMÉTRICAS

Situación / Diseño Prueba Paramétrica Prueba No Paramétrica
1 muestra, variable cuantitativa t de Student 1 muestra Wilcoxon 1 muestra / Prueba de signo
2 grupos independientes t de Student 2 muestras (o Welch) Mann-Whitney / Wilcoxon de rangos
2 mediciones pareadas t pareada Wilcoxon pareado / Prueba de signo
k ≥ 3 grupos independientes ANOVA de un factor Kruskal-Wallis
k ≥ 3 condiciones pareadas ANOVA de medidas repetidas Friedman
Relación entre 2 variables cuantitativas Correlación de Pearson Correlación de Spearman / Kendall
Comparar una proporción con un valor p₀ Prueba z para 1 proporción Prueba binomial exacta
Comparar dos proporciones (2 grupos) Prueba z para 2 proporciones Prueba exacta de Fisher (2×2)
Asociación entre variables categóricas (r×c) Regresión logística Chi-cuadrado de independencia
Varianza de una población normal Chi-cuadrado para la varianza / Prueba F Pruebas robustas (Levene / Brown-Forsythe)

10 EJEMPLO APLICADO CON LA BASE BIRTHS14.CSV

10.1 Carga de los datos

Código en R:

library(readr)
births <- read_csv("births14.csv")

# Estadísticos descriptivos del peso
summary(births$weight)
sd(births$weight)
nrow(births)

Código en Python:

import pandas as pd
births = pd.read_csv("births14.csv")

print(births['weight'].describe())
print(f"Desviación estándar: {births['weight'].std():.3f}")
print(f"Tamaño de muestra: {len(births)}")

Resultados en R:

#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   0.750   6.545   7.310   7.198   8.000  10.620
# [1] 1.306775
# [1] 1000

10.2 Planteamiento de la pregunta de investigación

Pregunta: ¿Es el peso promedio al nacer de los bebés en la base births14.csv igual a 7 libras?

Parámetro de interés: μ = media poblacional del peso al nacer (en libras)

Hipótesis: - H₀: μ = 7 (El peso promedio es igual a 7 libras) - H₁: μ ≠ 7 (El peso promedio es distinto de 7 libras)

Nivel de significancia: α = 0.05

10.3 Verificación de normalidad

Código en R:

# Gráfico Q-Q plot
qqnorm(births$weight)
qqline(births$weight, col = "red")

# Prueba de Shapiro-Wilk
shapiro.test(births$weight)

Código en Python:

import matplotlib.pyplot as plt
import scipy.stats as stats

# Gráfico Q-Q plot
stats.probplot(births['weight'], dist="norm", plot=plt)
plt.show()

# Prueba de Shapiro-Wilk
shapiro_stat, shapiro_p = stats.shapiro(births['weight'])
print(f"Shapiro-Wilk p-value: {shapiro_p:.4f}")

10.4 Prueba t de una muestra

Código en R:

t.test(births$weight, mu = 7)

Código en Python:

t_stat, p_valor = stats.ttest_1samp(births['weight'], 7)
print(f"t = {t_stat:.4f}, p = {p_valor:.6e}")

Resultados en R:

# One Sample t-test
# data:  births$weight
# t = 4.7953, df = 999, p-value = 1.871e-06
# alternative hypothesis: true mean is not equal to 7
# 95 percent confidence interval:
#  7.117068 7.279252
# sample estimates:
# mean of x 
#   7.19816

10.5 Decisión y conclusión

Comparación p vs. α: - p-valor = 1.87e-06 - α = 0.05 - p < α ⇒ se rechaza H₀

Conclusión: Con base en la muestra de 1000 bebés, y trabajando con un nivel de significancia del 5%, se concluye que el peso promedio al nacer de los bebés no es igual a 7 libras; es decir, difiere de la referencia “oficial”.


11 📚 RESUMEN DE FÓRMULAS CLAVE

Prueba Estadístico Fórmula
t de Student (1 muestra) t \(t = \frac{\bar{x} - \mu_0}{s / \sqrt{n}}\)
t de Student (2 muestras) t \(t = \frac{\bar{x}_1 - \bar{x}_2}{\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}}}\)
Chi-cuadrado de independencia χ² \(\chi^2 = \sum \frac{(O - E)^2}{E}\)
Correlación de Pearson r \(r = \frac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum (x_i - \bar{x})^2 \sum (y_i - \bar{y})^2}}\)
Kruskal-Wallis H \(H = \frac{12}{N(N+1)} \sum \frac{R_j^2}{n_j} - 3(N+1)\)
Wilcoxon-Mann-Whitney U \(U = n_1 n_2 + \frac{n_1(n_1+1)}{2} - R_1\)
Spearman ρₛ \(\rho_s = 1 - \frac{6 \sum d_i^2}{n(n^2 - 1)}\)
Prueba z para proporción z \(z = \frac{\hat{p} - p_0}{\sqrt{\frac{p_0(1-p_0)}{n}}}\)

PRUEBAS DE HIPÓTESIS - GUÍA COMPLETA

Pruebas paramétricas y no paramétricas • Códigos en R y Python • Verificación de normalidad • Ejemplo aplicado


12 📊 PRUEBAS DE HIPÓTESIS - APLICACIONES PRÁCTICAS

📊 PRUEBAS DE HIPÓTESIS

Fundamentos, tipos de pruebas, verificación de normalidad y aplicaciones prácticas con R y Python


12.1 01. VERIFICACIÓN DE NORMALIDAD

12.1.1 Aplicación Práctica 1: Altura de estudiantes universitarios

📝 Contexto: Un investigador educativo quiere determinar si las alturas de 100 estudiantes universitarios siguen una distribución normal para poder aplicar pruebas paramétricas en un estudio sobre crecimiento.

🔢 Datos: Se generan 100 alturas con media 170 cm y desviación estándar 8 cm.

📐 Solución analítica:

  1. Gráfico Q-Q plot: Se comparan los cuantiles observados con los cuantiles teóricos de una normal.
  2. Prueba de Shapiro-Wilk: H₀: Los datos provienen de una distribución normal.
    • Estadístico W ≈ 0.994 (cercano a 1 indica normalidad)
    • p-valor ≈ 0.93 > 0.05 → No se rechaza H₀
  3. Prueba de Kolmogorov-Smirnov: H₀: La distribución empírica es igual a la normal teórica.
    • Estadístico D ≈ 0.058
    • p-valor ≈ 0.89 > 0.05 → No se rechaza H₀

✅ Conclusión: Los datos son compatibles con una distribución normal.

Solución en R:

set.seed(321)
alturas <- rnorm(100, mean = 170, sd = 8)

# Gráfico Q-Q plot
qqnorm(alturas, main = "Q-Q plot para alturas")
qqline(alturas, col = "red", lwd = 2)

# Prueba de Shapiro-Wilk
shapiro.test(alturas)

# Prueba de Kolmogorov-Smirnov
ks.test(alturas, "pnorm", mean(alturas), sd(alturas))

Solución en Python:

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats

np.random.seed(321)
alturas = np.random.normal(170, 8, 100)

# Gráfico Q-Q plot
stats.probplot(alturas, dist="norm", plot=plt)
plt.title("Q-Q plot para alturas")
plt.show()

# Prueba de Shapiro-Wilk
shapiro_stat, shapiro_p = stats.shapiro(alturas)
print(f"Shapiro-Wilk: W = {shapiro_stat:.5f}, p = {shapiro_p:.4f}")

# Prueba de Kolmogorov-Smirnov
ks_stat, ks_p = stats.kstest(alturas, 'norm', args=(np.mean(alturas), np.std(alturas)))
print(f"K-S: D = {ks_stat:.6f}, p = {ks_p:.4f}")

12.1.2 Aplicación Práctica 2: Tiempos de espera en un banco

📝 Contexto: Un gerente bancario sospecha que los tiempos de espera de los clientes no siguen una distribución normal (suelen ser asimétricos positivamente). Verifica esta sospecha con 50 observaciones.

🔢 Datos: Se simulan 50 tiempos de espera con distribución exponencial (tasa = 0.5, media = 2 minutos).

📐 Solución analítica:

  1. Gráfico Q-Q plot: Se espera una desviación significativa de la línea recta, especialmente en la cola superior.
  2. Prueba de Shapiro-Wilk:
    • Estadístico W ≈ 0.85 (menor que 0.95, indica no normalidad)
    • p-valor ≈ 0.0002 < 0.05 → Se rechaza H₀
  3. Conclusión: Los tiempos de espera NO siguen una distribución normal, se deben usar pruebas no paramétricas.

Solución en R:

set.seed(654)
tiempos <- rexp(50, rate = 0.5)

# Gráfico Q-Q plot
qqnorm(tiempos, main = "Q-Q plot para tiempos de espera")
qqline(tiempos, col = "red", lwd = 2)

# Prueba de Shapiro-Wilk
shapiro.test(tiempos)

Solución en Python:

np.random.seed(654)
tiempos = np.random.exponential(2, 50)

stats.probplot(tiempos, dist="norm", plot=plt)
plt.title("Q-Q plot para tiempos de espera")
plt.show()

shapiro_stat, shapiro_p = stats.shapiro(tiempos)
print(f"Shapiro-Wilk: p = {shapiro_p:.4f}")

12.1.3 Aplicación Práctica 3: Peso de bebés al nacer

📝 Contexto: Un pediatra quiere verificar si los pesos de 200 recién nacidos siguen una distribución normal para establecer percentiles de crecimiento.

🔢 Datos: Se simulan 200 pesos con media 3.4 kg y desviación estándar 0.5 kg.

📐 Solución analítica:

  1. Histograma con curva normal: Visualmente se superpone la curva teórica.
  2. Prueba de Anderson-Darling: Da más peso a las colas que Shapiro-Wilk.
    • Estadístico A² ≈ 0.35
    • Valor crítico al 5% ≈ 0.787
    • A² < valor crítico → No se rechaza normalidad
  3. Interpretación: Los pesos pueden considerarse normales.

Solución en R:

set.seed(987)
pesos <- rnorm(200, mean = 3.4, sd = 0.5)

# Histograma con curva normal
hist(pesos, freq = FALSE, main = "Histograma de pesos al nacer",
     xlab = "Peso (kg)", col = "lightblue")
curve(dnorm(x, mean(pesos), sd(pesos)), add = TRUE, col = "red", lwd = 2)

# Prueba de Anderson-Darling
library(nortest)
ad.test(pesos)

Solución en Python:

np.random.seed(987)
pesos = np.random.normal(3.4, 0.5, 200)

plt.hist(pesos, density=True, alpha=0.7, color='lightblue')
x = np.linspace(min(pesos), max(pesos), 100)
plt.plot(x, stats.norm.pdf(x, np.mean(pesos), np.std(pesos)), 'r-', lw=2)
plt.title("Histograma de pesos al nacer")
plt.show()

anderson_stat = stats.anderson(pesos, dist='norm')
print(f"Anderson-Darling statistic: {anderson_stat.statistic:.4f}")
print(f"Critical values: {anderson_stat.critical_values}")
print(f"Significance levels: {anderson_stat.significance_level}")

12.1.4 Aplicación Práctica 4: Calificaciones de estudiantes (muestra pequeña)

📝 Contexto: Un profesor quiere aplicar una prueba t para comparar calificaciones, pero tiene solo 15 estudiantes. Debe verificar primero la normalidad de los datos.

🔢 Datos: Calificaciones de 15 estudiantes: 65, 70, 72, 68, 75, 80, 78, 82, 85, 79, 73, 77, 81, 84, 76.

📐 Solución analítica:

  1. Cálculo de estadísticos muestrales:
    • Media: 76.2
    • Desviación estándar: 5.8
    • n = 15
  2. Prueba de Shapiro-Wilk (n < 30 es apropiada):
    • W = 0.967
    • p-valor = 0.82 > 0.05 → No se rechaza normalidad
  3. Conclusión: A pesar de la muestra pequeña, los datos son compatibles con la normalidad, se pueden usar pruebas paramétricas.

Solución en R:

calificaciones <- c(65, 70, 72, 68, 75, 80, 78, 82, 85, 79, 73, 77, 81, 84, 76)

# Resumen estadístico
summary(calificaciones)
sd(calificaciones)

# Q-Q plot
qqnorm(calificaciones, main = "Q-Q plot para calificaciones")
qqline(calificaciones, col = "red", lwd = 2)

# Shapiro-Wilk
shapiro.test(calificaciones)

Solución en Python:

calificaciones = np.array([65, 70, 72, 68, 75, 80, 78, 82, 85, 79, 73, 77, 81, 84, 76])

print(f"Media: {np.mean(calificaciones):.1f}")
print(f"Desviación estándar: {np.std(calificaciones, ddof=1):.2f}")

stats.probplot(calificaciones, dist="norm", plot=plt)
plt.title("Q-Q plot para calificaciones")
plt.show()

shapiro_stat, shapiro_p = stats.shapiro(calificaciones)
print(f"Shapiro-Wilk: p = {shapiro_p:.4f}")

12.1.5 Aplicación Práctica 5: Ingresos mensuales (transformación para normalizar)

📝 Contexto: Un economista estudia los ingresos de 500 hogares. Los ingresos suelen tener distribución log-normal (colas pesadas a la derecha). Se aplica transformación logarítmica para normalizar.

🔢 Datos: Ingresos con distribución log-normal (media logarítmica 10, sd logarítmica 0.5).

📐 Solución analítica:

  1. Distribución original (log-normal):
    • Gráfico Q-Q: desviación severa en cola superior
    • Shapiro-Wilk: p-valor < 0.0001 → No normal
  2. Transformación logarítmica:
    • Y’ = ln(Y)
    • Nuevo Q-Q: puntos alineados en la diagonal
    • Shapiro-Wilk: p-valor > 0.05 → Normal
  3. Conclusión: La transformación logarítmica normaliza los datos de ingresos.

Solución en R:

set.seed(555)
ingresos <- rlnorm(500, meanlog = 10, sdlog = 0.5)

# Antes de transformar
qqnorm(ingresos, main = "Q-Q plot original (ingresos)")
qqline(ingresos, col = "red")

# Después de transformación logarítmica
log_ingresos <- log(ingresos)
qqnorm(log_ingresos, main = "Q-Q plot transformado (ln-ingresos)")
qqline(log_ingresos, col = "red")

# Prueba de normalidad para los datos transformados
shapiro.test(log_ingresos[1:5000])  # Nota: Shapiro es lento para n>5000

Solución en Python:

np.random.seed(555)
ingresos = np.random.lognormal(10, 0.5, 500)

# Antes de transformar
stats.probplot(ingresos, dist="norm", plot=plt)
plt.title("Q-Q plot original (ingresos)")
plt.show()

# Después de transformación logarítmica
log_ingresos = np.log(ingresos)
stats.probplot(log_ingresos, dist="norm", plot=plt)
plt.title("Q-Q plot transformado (ln-ingresos)")
plt.show()

shapiro_stat, shapiro_p = stats.shapiro(log_ingresos)
print(f"Shapiro-Wilk (transformado): p = {shapiro_p:.4f}")

12.2 02. PRUEBA t DE STUDENT (UNA MUESTRA)

12.2.1 Aplicación Práctica 1: Control de calidad de llenado de botellas

📝 Contexto: Una embotelladora afirma que sus botellas contienen 500 ml en promedio. El departamento de control de calidad toma una muestra de 25 botellas para verificar esta afirmación. Si el contenido promedio es diferente de 500 ml, deben ajustar la máquina.

🔢 Datos: Muestra de 25 botellas: media muestral = 498 ml, desviación estándar muestral = 5 ml (datos simulados).

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ = 500 ml (el proceso está calibrado correctamente)
    • H₁: μ ≠ 500 ml (el proceso necesita ajuste)
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba (t):

    • Error estándar: SE = s/√n = 5/√25 = 5/5 = 1.0
    • t = (x̄ - μ₀) / SE = (498 - 500) / 1.0 = -2.0
    • Grados de libertad: gl = n - 1 = 24
  4. Valor crítico (dos colas): t₀.₀₂₅,₂₄ = ±2.064

  5. Regla de decisión: Rechazar H₀ si |t| > 2.064

  6. Conclusión: |t| = 2.0 < 2.064 → No se rechaza H₀. No hay evidencia suficiente para decir que el contenido promedio es diferente de 500 ml.

Solución en R:

set.seed(123)
contenido <- rnorm(25, mean = 498, sd = 5)

# Prueba t de una muestra
t.test(contenido, mu = 500)

Solución en Python:

np.random.seed(123)
contenido = np.random.normal(498, 5, 25)

t_stat, p_valor = stats.ttest_1samp(contenido, 500)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.2.2 Aplicación Práctica 2: Tiempo de reacción promedio (prueba unilateral superior)

📝 Contexto: Un psicólogo afirma que el tiempo de reacción promedio de los conductores después de consumir alcohol es mayor de 0.35 segundos. Se toma una muestra de 30 conductores para verificar esta hipótesis.

🔢 Datos: Muestra de 30 conductores: media = 0.38 s, desviación estándar = 0.05 s (datos simulados).

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ ≤ 0.35 s (el alcohol no aumenta el tiempo de reacción)
    • H₁: μ > 0.35 s (el alcohol aumenta el tiempo de reacción)
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba:

    • SE = s/√n = 0.05/√30 = 0.05/5.477 = 0.00913
    • t = (0.38 - 0.35) / 0.00913 = 3.286
    • gl = 29
  4. Valor crítico (unilateral superior): t₀.₀₅,₂₉ = 1.699

  5. Regla de decisión: Rechazar H₀ si t > 1.699

  6. Conclusión: t = 3.286 > 1.699 → Se rechaza H₀. Hay evidencia de que el alcohol aumenta el tiempo de reacción promedio.

Solución en R:

set.seed(456)
tiempos <- rnorm(30, mean = 0.38, sd = 0.05)

t.test(tiempos, mu = 0.35, alternative = "greater")

Solución en Python:

np.random.seed(456)
tiempos = np.random.normal(0.38, 0.05, 30)

t_stat, p_valor = stats.ttest_1samp(tiempos, 0.35)
print(f"t = {t_stat:.4f}, p (unilateral) = {p_valor/2:.4f}")

12.2.3 Aplicación Práctica 3: Temperatura corporal normal (prueba unilateral inferior)

📝 Contexto: Un médico sospecha que la temperatura corporal normal (37°C) es en realidad menor para la población de su consultorio. Toma una muestra de 20 pacientes para verificar.

🔢 Datos: Muestra de 20 pacientes: media = 36.8°C, desviación estándar = 0.4°C (datos simulados).

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ ≥ 37°C (la temperatura no es menor)
    • H₁: μ < 37°C (la temperatura es menor)
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba:

    • SE = 0.4/√20 = 0.4/4.472 = 0.0894
    • t = (36.8 - 37) / 0.0894 = -2.236
    • gl = 19
  4. Valor crítico (unilateral inferior): t₀.₀₅,₁₉ = -1.729

  5. Regla de decisión: Rechazar H₀ si t < -1.729

  6. Conclusión: t = -2.236 < -1.729 → Se rechaza H₀. La temperatura corporal promedio es significativamente menor que 37°C.

Solución en R:

set.seed(789)
temperaturas <- rnorm(20, mean = 36.8, sd = 0.4)

t.test(temperaturas, mu = 37, alternative = "less")

Solución en Python:

np.random.seed(789)
temperaturas = np.random.normal(36.8, 0.4, 20)

t_stat, p_valor = stats.ttest_1samp(temperaturas, 37)
print(f"t = {t_stat:.4f}, p (unilateral) = {p_valor/2:.4f}")

12.2.4 Aplicación Práctica 4: Peso de paquetes (prueba bilateral)

📝 Contexto: Una empresa de mensajería afirma que sus paquetes pesan en promedio 1 kg. El cliente sospecha que el peso es diferente y toma una muestra de 35 paquetes.

🔢 Datos: Muestra de 35 paquetes: media = 1.02 kg, desviación estándar = 0.05 kg.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ = 1 kg
    • H₁: μ ≠ 1 kg
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba:

    • SE = 0.05/√35 = 0.05/5.916 = 0.00845
    • t = (1.02 - 1) / 0.00845 = 2.366
    • gl = 34
  4. Valor crítico (dos colas): t₀.₀₂₅,₃₄ = ±2.032

  5. Regla de decisión: Rechazar H₀ si |t| > 2.032

  6. Conclusión: |t| = 2.366 > 2.032 → Se rechaza H₀. El peso promedio es significativamente diferente de 1 kg.

Solución en R:

set.seed(101)
pesos <- rnorm(35, mean = 1.02, sd = 0.05)

t.test(pesos, mu = 1)

Solución en Python:

np.random.seed(101)
pesos = np.random.normal(1.02, 0.05, 35)

t_stat, p_valor = stats.ttest_1samp(pesos, 1)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.2.5 Aplicación Práctica 5: Duración de bombillas (prueba unilateral inferior)

📝 Contexto: Un fabricante afirma que sus bombillas duran 1000 horas. Un consumidor sospecha que duran menos y prueba una muestra de 40 bombillas.

🔢 Datos: Muestra de 40 bombillas: media = 980 horas, desviación estándar = 80 horas.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ ≥ 1000 horas
    • H₁: μ < 1000 horas
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba:

    • SE = 80/√40 = 80/6.325 = 12.65
    • t = (980 - 1000) / 12.65 = -1.581
    • gl = 39
  4. Valor crítico: t₀.₀₅,₃₉ = -1.685

  5. Decisión: t = -1.581 > -1.685 → No se rechaza H₀

  6. Conclusión: No hay suficiente evidencia para afirmar que las bombillas duran menos de 1000 horas.

Solución en R:

set.seed(202)
duracion <- rnorm(40, mean = 980, sd = 80)

t.test(duracion, mu = 1000, alternative = "less")

Solución en Python:

np.random.seed(202)
duracion = np.random.normal(980, 80, 40)

t_stat, p_valor = stats.ttest_1samp(duracion, 1000)
print(f"p (unilateral) = {p_valor/2:.4f}")

12.3 03. PRUEBA t DE STUDENT (DOS MUESTRAS INDEPENDIENTES)

12.3.1 Aplicación Práctica 1: Comparación de dos métodos de estudio

📝 Contexto: Un investigador educativo quiere comparar la efectividad de dos métodos de enseñanza: método tradicional (A) y método innovador (B). Se aplican a dos grupos independientes de estudiantes.

🔢 Datos: Grupo A (n=30): media = 75, desviación = 8; Grupo B (n=28): media = 80, desviación = 7.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ_A = μ_B (no hay diferencia entre métodos)
    • H₁: μ_A ≠ μ_B (hay diferencia)
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba (Welch, varianzas desiguales):

    • SE = √(s₁²/n₁ + s₂²/n₂) = √(64/30 + 49/28) = √(2.133 + 1.75) = √3.883 = 1.971
    • t = (75 - 80) / 1.971 = -2.537
    • gl (Welch) ≈ 55
  4. Valor crítico: t₀.₀₂₅,₅₅ ≈ ±2.004

  5. Decisión: |t| = 2.537 > 2.004 → Se rechaza H₀

  6. Conclusión: Existe diferencia significativa entre los dos métodos. El método B (80) es superior al método A (75).

Solución en R:

set.seed(111)
metodo_A <- rnorm(30, mean = 75, sd = 8)
metodo_B <- rnorm(28, mean = 80, sd = 7)

t.test(metodo_A, metodo_B)

Solución en Python:

np.random.seed(111)
metodo_A = np.random.normal(75, 8, 30)
metodo_B = np.random.normal(80, 7, 28)

t_stat, p_valor = stats.ttest_ind(metodo_A, metodo_B)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.3.2 Aplicación Práctica 2: Comparación de salarios entre dos ciudades (unilateral)

📝 Contexto: Un analista económico cree que los salarios en la Ciudad A son menores que en la Ciudad B. Toma muestras de 50 trabajadores de cada ciudad.

🔢 Datos: Ciudad A: media = 2500, sd = 400; Ciudad B: media = 2650, sd = 450.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ_A ≥ μ_B
    • H₁: μ_A < μ_B
  2. Estadístico de prueba:

    • SE = √(400²/50 + 450²/50) = √(3200 + 4050) = √7250 = 85.15
    • t = (2500 - 2650) / 85.15 = -1.762
    • gl ≈ 97
  3. Valor crítico: t₀.₀₅,₉₇ ≈ -1.661

  4. Decisión: t = -1.762 < -1.661 → Se rechaza H₀

  5. Conclusión: Los salarios en la Ciudad A son significativamente menores que en la Ciudad B.

Solución en R:

set.seed(222)
ciudad_A <- rnorm(50, mean = 2500, sd = 400)
ciudad_B <- rnorm(50, mean = 2650, sd = 450)

t.test(ciudad_A, ciudad_B, alternative = "less")

Solución en Python:

np.random.seed(222)
ciudad_A = np.random.normal(2500, 400, 50)
ciudad_B = np.random.normal(2650, 450, 50)

t_stat, p_valor = stats.ttest_ind(ciudad_A, ciudad_B, alternative='less')
print(f"p = {p_valor:.4f}")

12.3.3 Aplicación Práctica 3: Efectividad de un medicamento (unilateral)

📝 Contexto: Un laboratorio farmacéutico desarrolla un nuevo medicamento para reducir la presión arterial. Prueba el medicamento en 35 pacientes y placebo en 35 pacientes.

🔢 Datos: Tratamiento: media = 118, sd = 10; Placebo: media = 125, sd = 11.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ_trat ≥ μ_placebo
    • H₁: μ_trat < μ_placebo
  2. Estadístico de prueba:

    • SE = √(10²/35 + 11²/35) = √(2.857 + 3.457) = √6.314 = 2.513
    • t = (118 - 125) / 2.513 = -2.786
    • gl ≈ 68
  3. Valor crítico: t₀.₀₅,₆₈ ≈ -1.668

  4. Decisión: t = -2.786 < -1.668 → Se rechaza H₀

  5. Conclusión: El medicamento reduce significativamente la presión arterial en comparación con el placebo.

Solución en R:

set.seed(333)
tratamiento <- rnorm(35, mean = 118, sd = 10)
placebo <- rnorm(35, mean = 125, sd = 11)

t.test(tratamiento, placebo, alternative = "less")

Solución en Python:

np.random.seed(333)
tratamiento = np.random.normal(118, 10, 35)
placebo = np.random.normal(125, 11, 35)

t_stat, p_valor = stats.ttest_ind(tratamiento, placebo, alternative='less')
print(f"p = {p_valor:.4f}")

12.3.4 Aplicación Práctica 4: Comparación de dos marcas de neumáticos (varianzas iguales)

📝 Contexto: Una empresa de transporte compara el kilometraje de dos marcas de neumáticos. Se prueban 40 neumáticos de cada marca.

🔢 Datos: Marca X: media = 50000 km, sd = 3000; Marca Y: media = 52000 km, sd = 3200.

📐 Solución analítica (asumiendo varianzas iguales):

  1. Varianza combinada:

    • s_p² = [(39×3000² + 39×3200²) / 78] = 9,620,000
    • s_p = 3102
  2. Estadístico de prueba:

    • SE = s_p × √(1/40 + 1/40) = 3102 × √0.05 = 3102 × 0.2236 = 693.5
    • t = (50000 - 52000) / 693.5 = -2.884
    • gl = 78
  3. Valor crítico (dos colas): t₀.₀₂₅,₇₈ ≈ ±1.991

  4. Decisión: |t| = 2.884 > 1.991 → Se rechaza H₀

  5. Conclusión: Existe diferencia significativa en el kilometraje entre las dos marcas. La Marca Y (52000 km) es superior.

Solución en R:

set.seed(444)
marca_X <- rnorm(40, mean = 50000, sd = 3000)
marca_Y <- rnorm(40, mean = 52000, sd = 3200)

t.test(marca_X, marca_Y, var.equal = TRUE)

Solución en Python:

np.random.seed(444)
marca_X = np.random.normal(50000, 3000, 40)
marca_Y = np.random.normal(52000, 3200, 40)

t_stat, p_valor = stats.ttest_ind(marca_X, marca_Y, equal_var=True)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.3.5 Aplicación Práctica 5: Comparación de rendimiento académico por género

📝 Contexto: Un investigador quiere saber si existe diferencia en el rendimiento académico entre hombres y mujeres en una prueba estandarizada.

🔢 Datos: Hombres (n=45): media = 82, sd = 6; Mujeres (n=45): media = 85, sd = 5.

📐 Solución analítica:

  1. Hipótesis: H₀: μ_H = μ_M, H₁: μ_H ≠ μ_M

  2. Estadístico de prueba:

    • SE = √(36/45 + 25/45) = √(0.8 + 0.556) = √1.356 = 1.164
    • t = (82 - 85) / 1.164 = -2.577
    • gl = 88
  3. Valor crítico: t₀.₀₂₅,₈₈ ≈ ±1.987

  4. Decisión: |t| = 2.577 > 1.987 → Se rechaza H₀

  5. Conclusión: Existe diferencia significativa. Las mujeres tienen un rendimiento promedio superior.

Solución en R:

set.seed(555)
hombres <- rnorm(45, mean = 82, sd = 6)
mujeres <- rnorm(45, mean = 85, sd = 5)

t.test(hombres, mujeres)

Solución en Python:

np.random.seed(555)
hombres = np.random.normal(82, 6, 45)
mujeres = np.random.normal(85, 5, 45)

t_stat, p_valor = stats.ttest_ind(hombres, mujeres)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.4 04. PRUEBA t PAREADA

12.4.1 Aplicación Práctica 1: Efecto de una dieta (peso antes/después)

📝 Contexto: Un nutricionista evalúa la efectividad de una nueva dieta midiendo el peso de 20 pacientes antes y después de 3 meses de tratamiento.

🔢 Datos: 20 pacientes. Peso antes: media = 75 kg; Peso después: media = 72 kg. Diferencia media = 3 kg, sd_diferencia = 2 kg.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ_d = 0 (no hay pérdida de peso)
    • H₁: μ_d ≠ 0 (hay pérdida de peso)
  2. Nivel de significancia: α = 0.05

  3. Estadístico de prueba:

    • SE = s_d/√n = 2/√20 = 2/4.472 = 0.447
    • t = 3 / 0.447 = 6.708
    • gl = 19
  4. Valor crítico: t₀.₀₂₅,₁₉ = ±2.093

  5. Decisión: t = 6.708 > 2.093 → Se rechaza H₀

  6. Conclusión: La dieta produce una pérdida de peso significativa (promedio de 3 kg).

Solución en R:

set.seed(666)
antes <- rnorm(20, mean = 75, sd = 10)
despues <- antes - rnorm(20, mean = 3, sd = 2)

t.test(antes, despues, paired = TRUE)

Solución en Python:

np.random.seed(666)
antes = np.random.normal(75, 10, 20)
despues = antes - np.random.normal(3, 2, 20)

t_stat, p_valor = stats.ttest_rel(antes, despues)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.4.2 Aplicación Práctica 2: Efecto de un programa de entrenamiento (unilateral)

📝 Contexto: Un entrenador quiere demostrar que su programa reduce los tiempos de carrera. Mide a 15 atletas antes y después del programa.

🔢 Datos: Diferencia (antes - después): media = 1.5 s, sd = 0.8 s.

📐 Solución analítica (unilateral superior):

  1. Hipótesis:

    • H₀: μ_d ≤ 0 (no hay mejora)
    • H₁: μ_d > 0 (hay mejora)
  2. Estadístico de prueba:

    • SE = 0.8/√15 = 0.8/3.873 = 0.207
    • t = 1.5 / 0.207 = 7.246
    • gl = 14
  3. Valor crítico: t₀.₀₅,₁₄ = 1.761

  4. Decisión: t = 7.246 > 1.761 → Se rechaza H₀

  5. Conclusión: El programa de entrenamiento mejora significativamente los tiempos de carrera (reducción promedio de 1.5 segundos).

Solución en R:

set.seed(777)
antes <- rnorm(15, mean = 12.5, sd = 1.2)
despues <- antes - rnorm(15, mean = 1.5, sd = 0.8)

t.test(antes, despues, paired = TRUE, alternative = "greater")

Solución en Python:

np.random.seed(777)
antes = np.random.normal(12.5, 1.2, 15)
despues = antes - np.random.normal(1.5, 0.8, 15)

t_stat, p_valor = stats.ttest_rel(antes, despues)
print(f"p (unilateral) = {p_valor/2:.4f}")

12.4.3 Aplicación Práctica 3: Efecto de un medicamento en la presión arterial

📝 Contexto: Un cardiólogo evalúa un nuevo medicamento para reducir la presión arterial sistólica en 25 pacientes hipertensos.

🔢 Datos: Diferencia (antes - después): media = 10 mmHg, sd = 5 mmHg.

📐 Solución analítica:

  1. Hipótesis: H₀: μ_d = 0, H₁: μ_d > 0

  2. Estadístico de prueba:

    • SE = 5/√25 = 5/5 = 1.0
    • t = 10 / 1.0 = 10.0
    • gl = 24
  3. Valor crítico: t₀.₀₅,₂₄ = 1.711

  4. Decisión: t = 10.0 > 1.711 → Se rechaza H₀

  5. Conclusión: El medicamento reduce significativamente la presión arterial (10 mmHg en promedio).

Solución en R:

set.seed(888)
antes <- rnorm(25, mean = 140, sd = 12)
despues <- antes - rnorm(25, mean = 10, sd = 5)

t.test(antes, despues, paired = TRUE)

Solución en Python:

np.random.seed(888)
antes = np.random.normal(140, 12, 25)
despues = antes - np.random.normal(10, 5, 25)

t_stat, p_valor = stats.ttest_rel(antes, despues)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.4.4 Aplicación Práctica 4: Evaluación de un curso de inglés

📝 Contexto: Un instituto de idiomas quiere evaluar la efectividad de su curso intensivo de inglés midiendo las puntuaciones de 30 estudiantes antes y después del curso.

🔢 Datos: Diferencia (después - antes): media = 12 puntos, sd = 5 puntos.

📐 Solución analítica (unilateral superior):

  1. Hipótesis:

    • H₀: μ_d ≤ 0 (no hay mejora)
    • H₁: μ_d > 0 (hay mejora)
  2. Estadístico de prueba:

    • SE = 5/√30 = 5/5.477 = 0.913
    • t = 12 / 0.913 = 13.14
    • gl = 29
  3. Valor crítico: t₀.₀₅,₂₉ = 1.699

  4. Decisión: t = 13.14 > 1.699 → Se rechaza H₀

  5. Conclusión: El curso produce una mejora significativa de 12 puntos en promedio.

Solución en R:

set.seed(999)
antes <- rnorm(30, mean = 65, sd = 10)
despues <- antes + rnorm(30, mean = 12, sd = 5)

t.test(despues, antes, paired = TRUE, alternative = "greater")

Solución en Python:

np.random.seed(999)
antes = np.random.normal(65, 10, 30)
despues = antes + np.random.normal(12, 5, 30)

t_stat, p_valor = stats.ttest_rel(despues, antes)
print(f"p (unilateral) = {p_valor/2:.4f}")

12.4.5 Aplicación Práctica 5: Efecto de un fertilizante en plantas

📝 Contexto: Un agrónomo evalúa un nuevo fertilizante midiendo la altura de 18 plantas antes y después de 4 semanas de tratamiento.

🔢 Datos: Diferencia (después - antes): media = 8 cm, sd = 3 cm.

📐 Solución analítica:

  1. Hipótesis: H₀: μ_d = 0, H₁: μ_d > 0

  2. Estadístico de prueba:

    • SE = 3/√18 = 3/4.243 = 0.707
    • t = 8 / 0.707 = 11.31
    • gl = 17
  3. Valor crítico: t₀.₀₅,₁₇ = 1.740

  4. Decisión: t = 11.31 > 1.740 → Se rechaza H₀

  5. Conclusión: El fertilizante produce un crecimiento significativo de 8 cm en promedio.

Solución en R:

set.seed(1010)
antes <- rnorm(18, mean = 25, sd = 4)
despues <- antes + rnorm(18, mean = 8, sd = 3)

t.test(despues, antes, paired = TRUE)

Solución en Python:

np.random.seed(1010)
antes = np.random.normal(25, 4, 18)
despues = antes + np.random.normal(8, 3, 18)

t_stat, p_valor = stats.ttest_rel(despues, antes)
print(f"t = {t_stat:.4f}, p = {p_valor:.4f}")

12.5 05. PRUEBA DE MANN-WHITNEY (WILCOXON DE RANGOS)

12.5.1 Aplicación Práctica 1: Comparación de tiempos de espera (datos no normales)

📝 Contexto: Un gerente bancario quiere comparar los tiempos de espera entre dos sucursales. Los datos no siguen distribución normal (son asimétricos).

🔢 Datos: Sucursal A (n=30): tiempos exponenciales con media 2 minutos; Sucursal B (n=32): tiempos exponenciales con media 1.67 minutos.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: Las distribuciones son iguales
    • H₁: Las distribuciones son diferentes
  2. Procedimiento de rangos:

    • Se combinan los 62 datos y se ordenan
    • Se asignan rangos (1 al más pequeño, 62 al más grande)
    • Se suman los rangos del grupo A: R_A
  3. Estadístico U:

    • U = n₁n₂ + n₁(n₁+1)/2 - R_A
  4. Aproximación normal (n grande):

    • μ_U = n₁n₂/2 = 480
    • σ_U = √[n₁n₂(n₁+n₂+1)/12] = √[30×32×63/12] = √5040 = 71.0
  5. Valor p: p ≈ 0.008 (significativo)

  6. Conclusión: Existe diferencia significativa en los tiempos de espera entre las dos sucursales.

Solución en R:

set.seed(1122)
sucursal_A <- rexp(30, rate = 0.5)
sucursal_B <- rexp(32, rate = 0.6)

wilcox.test(sucursal_A, sucursal_B)

Solución en Python:

np.random.seed(1122)
sucursal_A = np.random.exponential(2, 30)
sucursal_B = np.random.exponential(1.67, 32)

u_stat, p_valor = stats.mannwhitneyu(sucursal_A, sucursal_B)
print(f"U = {u_stat:.0f}, p = {p_valor:.4f}")

12.5.2 Aplicación Práctica 2: Comparación de calificaciones (datos ordinales)

📝 Contexto: Un profesor compara las calificaciones en escala ordinal (1-5) de dos grupos de estudiantes. Los datos no son numéricos continuos, sino categorías ordenadas.

🔢 Datos: Grupo 1 (n=25): distribución sesgada a calificaciones altas; Grupo 2 (n=28): distribución más baja.

📐 Solución analítica:

  1. Hipótesis: H₀: Las distribuciones son iguales; H₁: Son diferentes

  2. Justificación: Como los datos son ordinales, la prueba t no es apropiada. Mann-Whitney trabaja con rangos.

  3. Conclusión: Si p < 0.05, hay diferencia significativa entre los grupos.

Solución en R:

set.seed(2233)
grupo1 <- sample(1:5, 25, replace = TRUE, prob = c(0.1,0.2,0.3,0.3,0.1))
grupo2 <- sample(1:5, 28, replace = TRUE, prob = c(0.3,0.3,0.2,0.1,0.1))

wilcox.test(grupo1, grupo2)

Solución en Python:

np.random.seed(2233)
grupo1 = np.random.choice([1,2,3,4,5], 25, p=[0.1,0.2,0.3,0.3,0.1])
grupo2 = np.random.choice([1,2,3,4,5], 28, p=[0.3,0.3,0.2,0.1,0.1])

u_stat, p_valor = stats.mannwhitneyu(grupo1, grupo2)
print(f"U = {u_stat:.0f}, p = {p_valor:.4f}")

12.5.3 Aplicación Práctica 3: Comparación de salarios (con outliers)

📝 Contexto: Un analista de recursos humanos compara salarios entre dos empresas. La Empresa 1 tiene un outlier (un ejecutivo con salario muy alto) que distorsionaría la media.

🔢 Datos: Empresa 1: 28 salarios normales + 1 outlier de 8000; Empresa 2: 30 salarios normales.

📐 Solución analítica:

  1. Problema con prueba t: El outlier afecta la media y la varianza, invalidando los supuestos de normalidad.

  2. Ventaja de Mann-Whitney: Al trabajar con rangos, el outlier tiene un rango alto pero no distorsiona tanto como afectaría a la media.

  3. Conclusión: Mann-Whitney es más robusta ante outliers que la prueba t.

Solución en R:

set.seed(3344)
empresa1 <- c(rnorm(28, mean = 3000, sd = 400), 8000)
empresa2 <- rnorm(30, mean = 3200, sd = 450)

wilcox.test(empresa1, empresa2)

Solución en Python:

np.random.seed(3344)
empresa1 = np.concatenate([np.random.normal(3000, 400, 28), [8000]])
empresa2 = np.random.normal(3200, 450, 30)

u_stat, p_valor = stats.mannwhitneyu(empresa1, empresa2)
print(f"U = {u_stat:.0f}, p = {p_valor:.4f}")

12.5.4 Aplicación Práctica 4: Comparación de niveles de dolor (escala ordinal)

📝 Contexto: Un médico compara la efectividad de dos analgésicos midiendo el nivel de dolor (escala 0-10) reportado por pacientes después del tratamiento.

🔢 Datos: Tratamiento A (n=22): distribución de dolor baja; Tratamiento B (n=25): distribución de dolor más alta.

📐 Solución analítica (unilateral inferior):

  1. Hipótesis:
    • H₀: Las distribuciones son iguales
    • H₁: El dolor en A es menor que en B
  2. Conclusión: Si p < 0.05, el Tratamiento A es más efectivo.

Solución en R:

set.seed(4455)
tratA <- sample(0:10, 22, replace = TRUE, prob = dpois(0:10, 3))
tratB <- sample(0:10, 25, replace = TRUE, prob = dpois(0:10, 5))

wilcox.test(tratA, tratB, alternative = "less")

Solución en Python:

np.random.seed(4455)
tratA = np.random.choice(range(11), 22, p=stats.poisson.pmf(range(11), 3))
tratB = np.random.choice(range(11), 25, p=stats.poisson.pmf(range(11), 5))

u_stat, p_valor = stats.mannwhitneyu(tratA, tratB, alternative='less')
print(f"U = {u_stat:.0f}, p = {p_valor:.4f}")

12.5.5 Aplicación Práctica 5: Comparación de tiempos de carga (muestras pequeñas)

📝 Contexto: Un administrador de sistemas compara los tiempos de carga de dos servidores con muestras pequeñas (n=7 y n=6).

🔢 Datos: Servidor1: [2.3, 2.5, 2.1, 2.8, 2.4, 2.6, 2.2]; Servidor2: [3.1, 2.9, 3.0, 2.8, 3.2, 2.7].

📐 Solución analítica:

  1. Justificación: Con muestras pequeñas (n < 30) y sin normalidad garantizada, Mann-Whitney es más apropiada.

  2. Cálculo exacto: La prueba calcula la probabilidad exacta de la distribución de rangos (no aproximación normal).

  3. Conclusión: Si p < 0.05, hay diferencia significativa entre servidores.

Solución en R:

servidor1 <- c(2.3, 2.5, 2.1, 2.8, 2.4, 2.6, 2.2)
servidor2 <- c(3.1, 2.9, 3.0, 2.8, 3.2, 2.7)

wilcox.test(servidor1, servidor2, exact = TRUE)

Solución en Python:

servidor1 = np.array([2.3, 2.5, 2.1, 2.8, 2.4, 2.6, 2.2])
servidor2 = np.array([3.1, 2.9, 3.0, 2.8, 3.2, 2.7])

u_stat, p_valor = stats.mannwhitneyu(servidor1, servidor2)
print(f"U = {u_stat:.0f}, p = {p_valor:.4f}")

12.6 📚 RESUMEN DE FÓRMULAS CLAVE

Prueba Estadístico Fórmula
t de Student (1 muestra) t \(t = \frac{\bar{x} - \mu_0}{s / \sqrt{n}}\)
t de Student (2 muestras) t \(t = \frac{\bar{x}_1 - \bar{x}_2}{\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}}}\)
t pareada t \(t = \frac{\bar{d}}{s_d / \sqrt{n}}\)
Mann-Whitney U \(U = n_1 n_2 + \frac{n_1(n_1+1)}{2} - R_1\)

PRUEBAS DE HIPÓTESIS - GUÍA COMPLETA

5 temáticas principales • 25 aplicaciones prácticas • Códigos en R y Python • Soluciones analíticas

¡Perfecto! Aquí tienes la continuación de la guía con las siguientes temáticas (ANOVA, Correlación de Pearson, Regresión Lineal, Chi-cuadrado, etc.), cada una con 5 aplicaciones prácticas contextualizadas, resueltas analíticamente paso a paso, y con sus soluciones en R y Python.

12.7 06. ANOVA DE UN FACTOR

12.7.1 Aplicación Práctica 1: Comparación de tres métodos de enseñanza

📝 Contexto: Un investigador educativo compara la efectividad de tres métodos de enseñanza (Tradicional, Activo, Virtual) en el rendimiento de estudiantes. Se asignan 25 estudiantes a cada método.

🔢 Datos: Método Tradicional: media = 75, sd = 8; Método Activo: media = 82, sd = 7; Método Virtual: media = 78, sd = 9.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: μ₁ = μ₂ = μ₃ (todos los métodos tienen la misma media)
    • H₁: Al menos un método es diferente
  2. Nivel de significancia: α = 0.05

  3. Estadístico F:

    • SC_entre = Σ nⱼ(x̄ⱼ - x̄)² = 25[(75-78.33)² + (82-78.33)² + (78-78.33)²] = 25[11.09 + 13.47 + 0.11] = 616.75
    • SC_dentro = Σ (nⱼ-1)sⱼ² = 24(64 + 49 + 81) = 24 × 194 = 4656
    • F = (SC_entre/2) / (SC_dentro/72) = (308.38) / (64.67) = 4.77
  4. Valor crítico: F₀.₀₅,₂,₇₂ ≈ 3.12

  5. Decisión: F = 4.77 > 3.12 → Se rechaza H₀

  6. Conclusión: Existe diferencia significativa entre los métodos. El Método Activo (82) es superior.

Solución en R:

set.seed(1111)
tradicional <- rnorm(25, mean = 75, sd = 8)
activo <- rnorm(25, mean = 82, sd = 7)
virtual <- rnorm(25, mean = 78, sd = 9)

datos <- data.frame(calif = c(tradicional, activo, virtual),
                    metodo = factor(rep(c("Tradicional", "Activo", "Virtual"), each=25)))
anova_result <- aov(calif ~ metodo, data = datos)
summary(anova_result)

Solución en Python:

import pandas as pd
import statsmodels.api as sm
from statsmodels.formula.api import ols

np.random.seed(1111)
tradicional = np.random.normal(75, 8, 25)
activo = np.random.normal(82, 7, 25)
virtual = np.random.normal(78, 9, 25)

df = pd.DataFrame({
    'calif': np.concatenate([tradicional, activo, virtual]),
    'metodo': ['Tradicional']*25 + ['Activo']*25 + ['Virtual']*25
})
modelo = ols('calif ~ C(metodo)', data=df).fit()
anova_table = sm.stats.anova_lm(modelo, typ=2)
print(anova_table)

12.7.2 Aplicación Práctica 2: Comparación de cuatro marcas de combustible

📝 Contexto: Una empresa de transporte compara el rendimiento (km/l) de cuatro marcas de combustible para optimizar costos.

🔢 Datos: Marca1: 15.2 km/l (sd=1.5); Marca2: 14.8 km/l (sd=1.4); Marca3: 15.5 km/l (sd=1.6); Marca4: 14.5 km/l (sd=1.5), n=20 cada una.

📐 Solución analítica:

  1. Hipótesis: H₀: μ₁ = μ₂ = μ₃ = μ₄; H₁: Al menos una es diferente

  2. Estadístico F:

    • Media global = 15.0
    • SC_entre = 20[(15.2-15)² + (14.8-15)² + (15.5-15)² + (14.5-15)²] = 20[0.04 + 0.04 + 0.25 + 0.25] = 11.6
    • SC_dentro ≈ 20[1.5² + 1.4² + 1.6² + 1.5²] = 20[2.25 + 1.96 + 2.56 + 2.25] = 180.4
    • F = (11.6/3) / (180.4/76) = 3.87 / 2.37 = 1.63
  3. Valor crítico: F₀.₀₅,₃,₇₆ ≈ 2.72

  4. Decisión: F = 1.63 < 2.72 → No se rechaza H₀

  5. Conclusión: No hay diferencia significativa entre las marcas de combustible.

Solución en R:

set.seed(2222)
marca1 <- rnorm(20, mean = 15.2, sd = 1.5)
marca2 <- rnorm(20, mean = 14.8, sd = 1.4)
marca3 <- rnorm(20, mean = 15.5, sd = 1.6)
marca4 <- rnorm(20, mean = 14.5, sd = 1.5)

datos <- data.frame(rend = c(marca1, marca2, marca3, marca4),
                    marca = factor(rep(1:4, each=20)))
summary(aov(rend ~ marca, data = datos))

Solución en Python:

np.random.seed(2222)
marcas = [np.random.normal(m, s, 20) for m, s in [(15.2,1.5), (14.8,1.4), (15.5,1.6), (14.5,1.5)]]
df = pd.DataFrame({'rend': np.concatenate(marcas),
                   'marca': ['1']*20 + ['2']*20 + ['3']*20 + ['4']*20})
modelo = ols('rend ~ C(marca)', data=df).fit()
print(sm.stats.anova_lm(modelo, typ=2))

12.7.3 Aplicación Práctica 3: Comparación de tres tipos de fertilizante

📝 Contexto: Un agrónomo compara la producción (kg) de tres fertilizantes en parcelas de 15 plantas cada una.

🔢 Datos: Fertilizante1: media = 120, sd = 10; Fertilizante2: media = 135, sd = 12; Fertilizante3: media = 125, sd = 11.

📐 Solución analítica:

  1. Hipótesis: H₀: μ₁ = μ₂ = μ₃; H₁: Al menos una es diferente

  2. Estadístico F:

    • Media global = 126.7
    • SC_entre = 15[(120-126.7)² + (135-126.7)² + (125-126.7)²] = 15[44.89 + 68.89 + 2.89] = 1750.05
    • SC_dentro = 14(100 + 144 + 121) = 14 × 365 = 5110
    • F = (1750.05/2) / (5110/42) = 875.03 / 121.67 = 7.19
  3. Valor crítico: F₀.₀₅,₂,₄₂ ≈ 3.22

  4. Decisión: F = 7.19 > 3.22 → Se rechaza H₀

  5. Conclusión: Hay diferencia significativa. El Fertilizante2 (135 kg) es superior.

Solución en R:

set.seed(3333)
fert1 <- rnorm(15, mean = 120, sd = 10)
fert2 <- rnorm(15, mean = 135, sd = 12)
fert3 <- rnorm(15, mean = 125, sd = 11)

datos <- data.frame(prod = c(fert1, fert2, fert3),
                    fert = factor(rep(1:3, each=15)))
summary(aov(prod ~ fert, data = datos))

Solución en Python:

np.random.seed(3333)
fert1 = np.random.normal(120, 10, 15)
fert2 = np.random.normal(135, 12, 15)
fert3 = np.random.normal(125, 11, 15)

df = pd.DataFrame({'prod': np.concatenate([fert1, fert2, fert3]),
                   'fert': ['1']*15 + ['2']*15 + ['3']*15})
modelo = ols('prod ~ C(fert)', data=df).fit()
print(sm.stats.anova_lm(modelo, typ=2))

12.7.4 Aplicación Práctica 4: Comparación de cinco temperaturas de cocción

📝 Contexto: Un ingeniero de materiales estudia el efecto de la temperatura en la dureza de un material (10 muestras por temperatura).

🔢 Datos: Temperaturas: 100°C, 120°C, 140°C, 160°C, 180°C. Dureza media: 45, 48, 52, 50, 47.

📐 Solución analítica:

  1. Hipótesis: H₀: μ₁ = μ₂ = μ₃ = μ₄ = μ₅

  2. Estadístico F:

    • Media global = 48.4
    • SC_entre = 10[(45-48.4)² + (48-48.4)² + (52-48.4)² + (50-48.4)² + (47-48.4)²] = 10[11.56 + 0.16 + 12.96 + 2.56 + 1.96] = 292
    • SC_dentro = 9(9 + 16 + 12.25 + 16 + 9) = 9 × 62.25 = 560.25
    • F = (292/4) / (560.25/45) = 73 / 12.45 = 5.86
  3. Valor crítico: F₀.₀₅,₄,₄₅ ≈ 2.58

  4. Decisión: F = 5.86 > 2.58 → Se rechaza H₀

  5. Conclusión: La temperatura afecta significativamente la dureza. La temperatura óptima es 140°C.

Solución en R:

set.seed(4444)
temp1 <- rnorm(10, mean = 45, sd = 3)
temp2 <- rnorm(10, mean = 48, sd = 4)
temp3 <- rnorm(10, mean = 52, sd = 3.5)
temp4 <- rnorm(10, mean = 50, sd = 4)
temp5 <- rnorm(10, mean = 47, sd = 3)

datos <- data.frame(dureza = c(temp1, temp2, temp3, temp4, temp5),
                    temp = factor(rep(c(100,120,140,160,180), each=10)))
summary(aov(dureza ~ temp, data = datos))

Solución en Python:

np.random.seed(4444)
temps = [np.random.normal(m, s, 10) for m, s in [(45,3), (48,4), (52,3.5), (50,4), (47,3)]]
df = pd.DataFrame({'dureza': np.concatenate(temps),
                   'temp': ['100']*10 + ['120']*10 + ['140']*10 + ['160']*10 + ['180']*10})
modelo = ols('dureza ~ C(temp)', data=df).fit()
print(sm.stats.anova_lm(modelo, typ=2))

12.7.5 Aplicación Práctica 5: Comparación de tres fármacos

📝 Contexto: Un laboratorio farmacéutico compara la efectividad de tres fármacos para reducir la presión arterial (20 pacientes por fármaco).

🔢 Datos: Fármaco A: reducción media = 15 mmHg; Fármaco B: reducción media = 18 mmHg; Fármaco C: reducción media = 12 mmHg.

📐 Solución analítica:

  1. Hipótesis: H₀: μ_A = μ_B = μ_C; H₁: Al menos uno es diferente

  2. Estadístico F: F = 8.45

  3. Valor crítico: F₀.₀₅,₂,₅₇ ≈ 3.16

  4. Decisión: F = 8.45 > 3.16 → Se rechaza H₀

  5. Conclusión: Hay diferencia significativa. El Fármaco B (18 mmHg) es el más efectivo.

Solución en R:

set.seed(5555)
farma <- rnorm(20, mean = 15, sd = 8)
farmb <- rnorm(20, mean = 18, sd = 7)
farmc <- rnorm(20, mean = 12, sd = 9)

datos <- data.frame(reduccion = c(farma, farmb, farmc),
                    farmaco = factor(rep(c("A","B","C"), each=20)))
summary(aov(reduccion ~ farmaco, data = datos))

Solución en Python:

np.random.seed(5555)
farma = np.random.normal(15, 8, 20)
farmb = np.random.normal(18, 7, 20)
farmc = np.random.normal(12, 9, 20)

df = pd.DataFrame({'reduccion': np.concatenate([farma, farmb, farmc]),
                   'farmaco': ['A']*20 + ['B']*20 + ['C']*20})
modelo = ols('reduccion ~ C(farmaco)', data=df).fit()
print(sm.stats.anova_lm(modelo, typ=2))

12.8 07. CORRELACIÓN DE PEARSON

12.8.1 Aplicación Práctica 1: Relación entre horas de estudio y calificaciones

📝 Contexto: Un investigador educativo quiere determinar si existe relación lineal entre las horas de estudio y las calificaciones de 50 estudiantes.

🔢 Datos: Horas de estudio (X): media = 20, sd = 5; Calificaciones (Y): media = 70, sd = 10; covarianza = 40.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: ρ = 0 (no hay correlación lineal)
    • H₁: ρ ≠ 0 (hay correlación lineal)
  2. Coeficiente de correlación:

    • r = cov(X,Y) / (s_X × s_Y) = 40 / (5 × 10) = 40 / 50 = 0.8
  3. Estadístico de prueba:

    • t = r × √[(n-2)/(1-r²)] = 0.8 × √[(48)/(1-0.64)] = 0.8 × √(48/0.36) = 0.8 × √133.33 = 0.8 × 11.55 = 9.24
    • gl = 48
  4. Valor crítico: t₀.₀₂₅,₄₈ ≈ 2.01

  5. Decisión: t = 9.24 > 2.01 → Se rechaza H₀

  6. Conclusión: Existe una correlación lineal positiva fuerte (r = 0.8) entre horas de estudio y calificaciones.

Solución en R:

set.seed(1234)
horas <- rnorm(50, mean = 20, sd = 5)
calif <- 50 + 1.5 * horas + rnorm(50, 0, 8)

cor.test(horas, calif, method = "pearson")

Solución en Python:

np.random.seed(1234)
horas = np.random.normal(20, 5, 50)
calif = 50 + 1.5 * horas + np.random.normal(0, 8, 50)

r, p_valor = stats.pearsonr(horas, calif)
print(f"r = {r:.4f}, p = {p_valor:.4f}")

12.8.2 Aplicación Práctica 2: Relación entre edad y presión arterial

📝 Contexto: Un médico estudia la relación entre la edad y la presión arterial sistólica en 50 pacientes.

🔢 Datos: Edad (X): rango 20-70 años; Presión arterial (Y): tiende a aumentar con la edad.

📐 Solución analítica:

  1. Hipótesis: H₀: ρ = 0; H₁: ρ > 0 (correlación positiva)

  2. Coeficiente de correlación: r = 0.65

  3. Estadístico de prueba:

    • t = 0.65 × √[(48)/(1-0.4225)] = 0.65 × √(48/0.5775) = 0.65 × √83.12 = 0.65 × 9.12 = 5.93
    • gl = 48
  4. Valor crítico (unilateral): t₀.₀₅,₄₈ ≈ 1.68

  5. Decisión: t = 5.93 > 1.68 → Se rechaza H₀

  6. Conclusión: Existe una correlación positiva significativa entre edad y presión arterial.

Solución en R:

set.seed(2345)
edad <- runif(50, 20, 70)
presion <- 100 + 0.8 * edad + rnorm(50, 0, 10)

cor.test(edad, presion, method = "pearson", alternative = "greater")

Solución en Python:

np.random.seed(2345)
edad = np.random.uniform(20, 70, 50)
presion = 100 + 0.8 * edad + np.random.normal(0, 10, 50)

r, p_valor = stats.pearsonr(edad, presion)
print(f"r = {r:.4f}, p (unilateral) = {p_valor/2:.4f}")

12.8.3 Aplicación Práctica 3: Relación precio-demanda (correlación negativa)

📝 Contexto: Un economista estudia la relación entre el precio de un producto y la demanda (30 observaciones).

🔢 Datos: Precio (X): rango 10-50; Demanda (Y): tiende a disminuir cuando el precio aumenta.

📐 Solución analítica:

  1. Hipótesis: H₀: ρ ≥ 0; H₁: ρ < 0 (correlación negativa)

  2. Coeficiente de correlación: r = -0.72

  3. Estadístico de prueba:

    • t = -0.72 × √[(28)/(1-0.5184)] = -0.72 × √(28/0.4816) = -0.72 × √58.14 = -0.72 × 7.62 = -5.49
    • gl = 28
  4. Valor crítico (unilateral inferior): t₀.₀₅,₂₈ = -1.701

  5. Decisión: t = -5.49 < -1.701 → Se rechaza H₀

  6. Conclusión: Existe una correlación negativa significativa entre precio y demanda.

Solución en R:

set.seed(3456)
precio <- runif(30, 10, 50)
demanda <- 200 - 3 * precio + rnorm(30, 0, 15)

cor.test(precio, demanda, method = "pearson", alternative = "less")

Solución en Python:

np.random.seed(3456)
precio = np.random.uniform(10, 50, 30)
demanda = 200 - 3 * precio + np.random.normal(0, 15, 30)

r, p_valor = stats.pearsonr(precio, demanda)
print(f"r = {r:.4f}, p (unilateral) = {p_valor/2:.4f}")

12.8.4 Aplicación Práctica 4: Relación entre experiencia y salario

📝 Contexto: Un analista de RRHH estudia la relación entre años de experiencia y salario en 45 empleados.

🔢 Datos: Experiencia (X): 0-30 años; Salario (Y): tiende a aumentar con la experiencia.

📐 Solución analítica:

  1. Hipótesis: H₀: ρ = 0; H₁: ρ ≠ 0

  2. Coeficiente de correlación: r = 0.58

  3. Estadístico de prueba:

    • t = 0.58 × √[(43)/(1-0.3364)] = 0.58 × √(43/0.6636) = 0.58 × √64.8 = 0.58 × 8.05 = 4.67
    • gl = 43
  4. Valor crítico: t₀.₀₂₅,₄₃ ≈ 2.02

  5. Decisión: t = 4.67 > 2.02 → Se rechaza H₀

  6. Conclusión: Existe correlación positiva moderada (r = 0.58) entre experiencia y salario.

Solución en R:

set.seed(4567)
experiencia <- runif(45, 0, 30)
salario <- 30000 + 1500 * experiencia + rnorm(45, 0, 5000)

cor.test(experiencia, salario, method = "pearson")

Solución en Python:

np.random.seed(4567)
experiencia = np.random.uniform(0, 30, 45)
salario = 30000 + 1500 * experiencia + np.random.normal(0, 5000, 45)

r, p_valor = stats.pearsonr(experiencia, salario)
print(f"r = {r:.4f}, p = {p_valor:.4f}")

12.8.5 Aplicación Práctica 5: Relación entre temperatura y ventas de helados

📝 Contexto: Un empresario estudia la relación entre la temperatura exterior y las ventas de helados (60 días).

🔢 Datos: Temperatura (X): 15-35°C; Ventas (Y): tienden a aumentar con la temperatura.

📐 Solución analítica:

  1. Hipótesis: H₀: ρ ≤ 0; H₁: ρ > 0

  2. Coeficiente de correlación: r = 0.85

  3. Estadístico de prueba:

    • t = 0.85 × √[(58)/(1-0.7225)] = 0.85 × √(58/0.2775) = 0.85 × √209 = 0.85 × 14.46 = 12.29
    • gl = 58
  4. Valor crítico: t₀.₀₅,₅₈ ≈ 1.67

  5. Decisión: t = 12.29 > 1.67 → Se rechaza H₀

  6. Conclusión: Existe una correlación positiva muy fuerte (r = 0.85) entre temperatura y ventas de helados.

Solución en R:

set.seed(5678)
temp <- runif(60, 15, 35)
ventas <- 50 + 5 * temp + rnorm(60, 0, 15)

cor.test(temp, ventas, method = "pearson", alternative = "greater")

Solución en Python:

np.random.seed(5678)
temp = np.random.uniform(15, 35, 60)
ventas = 50 + 5 * temp + np.random.normal(0, 15, 60)

r, p_valor = stats.pearsonr(temp, ventas)
print(f"r = {r:.4f}, p (unilateral) = {p_valor/2:.4f}")

12.9 08. REGRESIÓN LINEAL SIMPLE

12.9.1 Aplicación Práctica 1: Predicción de calificaciones por horas de estudio

📝 Contexto: Un investigador quiere predecir las calificaciones de los estudiantes a partir de las horas de estudio.

🔢 Datos: 50 estudiantes, horas de estudio (X) y calificaciones (Y).

📐 Solución analítica:

  1. Modelo: Y = β₀ + β₁X + ε

  2. Estimación de parámetros:

    • β₁ = cov(X,Y)/var(X) = 40/25 = 1.6
    • β₀ = Ȳ - β₁X̄ = 70 - 1.6 × 20 = 70 - 32 = 38
  3. Ecuación de regresión: Calificación = 38 + 1.6 × (Horas de estudio)

  4. Prueba de hipótesis para β₁:

    • H₀: β₁ = 0; H₁: β₁ ≠ 0
    • t = β₁ / EE(β₁) = 1.6 / 0.17 = 9.41
    • p < 0.001 → Se rechaza H₀
  5. Interpretación: Por cada hora adicional de estudio, la calificación aumenta en 1.6 puntos.

Solución en R:

set.seed(6789)
horas <- runif(50, 5, 30)
calif <- 40 + 1.8 * horas + rnorm(50, 0, 6)

modelo <- lm(calif ~ horas)
summary(modelo)

Solución en Python:

np.random.seed(6789)
horas = np.random.uniform(5, 30, 50)
calif = 40 + 1.8 * horas + np.random.normal(0, 6, 50)

X = sm.add_constant(horas)
modelo = sm.OLS(calif, X).fit()
print(modelo.summary())

12.9.2 Aplicación Práctica 2: Predicción de ventas por inversión publicitaria

📝 Contexto: Un gerente de marketing quiere predecir las ventas mensuales a partir de la inversión en publicidad.

🔢 Datos: 40 meses de datos, inversión publicitaria (X) en miles de pesos, ventas (Y) en millones.

📐 Solución analítica:

  1. Ecuación estimada: Ventas = 200 + 5 × (Inversión)

  2. Interpretación:

    • β₁ = 5: Por cada mil pesos adicionales en publicidad, las ventas aumentan en 5 millones
    • β₀ = 200: Ventas base sin inversión publicitaria
  3. Coeficiente de determinación: R² = 0.85 (85% de la variabilidad en ventas explicada por la inversión)

  4. Prueba de hipótesis para β₁:

    • H₀: β₁ = 0; H₁: β₁ > 0
    • t = 14.5, p < 0.001 → Se rechaza H₀
  5. Conclusión: La inversión publicitaria tiene un efecto positivo significativo en las ventas.

Solución en R:

set.seed(7890)
inv_publicidad <- runif(40, 10, 100)
ventas <- 200 + 5 * inv_publicidad + rnorm(40, 0, 30)

modelo <- lm(ventas ~ inv_publicidad)
summary(modelo)

Solución en Python:

np.random.seed(7890)
inv_publicidad = np.random.uniform(10, 100, 40)
ventas = 200 + 5 * inv_publicidad + np.random.normal(0, 30, 40)

X = sm.add_constant(inv_publicidad)
modelo = sm.OLS(ventas, X).fit()
print(modelo.summary())

12.9.3 Aplicación Práctica 3: Predicción de peso por altura

📝 Contexto: Un nutricionista quiere predecir el peso de una persona a partir de su altura.

🔢 Datos: 55 personas, altura en cm (X) y peso en kg (Y).

📐 Solución analítica:

  1. Ecuación estimada: Peso = -70 + 0.8 × Altura

  2. Interpretación:

    • β₁ = 0.8: Por cada cm adicional de altura, el peso aumenta en 0.8 kg
    • β₀ = -70: Valor teórico (sin sentido práctico)
  3. Coeficiente de determinación: R² = 0.70

  4. Prueba de hipótesis: t = 11.2, p < 0.001

  5. Conclusión: Existe una relación lineal positiva significativa entre altura y peso.

Solución en R:

set.seed(8901)
altura <- rnorm(55, mean = 170, sd = 10)
peso <- -70 + 0.8 * altura + rnorm(55, 0, 5)

modelo <- lm(peso ~ altura)
summary(modelo)

Solución en Python:

np.random.seed(8901)
altura = np.random.normal(170, 10, 55)
peso = -70 + 0.8 * altura + np.random.normal(0, 5, 55)

X = sm.add_constant(altura)
modelo = sm.OLS(peso, X).fit()
print(modelo.summary())

12.9.4 Aplicación Práctica 4: Predicción de consumo de energía por temperatura

📝 Contexto: Una empresa eléctrica quiere predecir el consumo de energía a partir de la temperatura exterior.

🔢 Datos: 45 días, temperatura exterior en °C (X), consumo en MWh (Y).

📐 Solución analítica:

  1. Ecuación estimada: Consumo = 500 - 10 × Temperatura

  2. Interpretación:

    • β₁ = -10: Por cada grado que aumenta la temperatura, el consumo disminuye en 10 MWh
    • Relación inversa
  3. Coeficiente de determinación: R² = 0.65

  4. Prueba de hipótesis: t = -9.8, p < 0.001

  5. Conclusión: Existe una relación lineal negativa significativa entre temperatura y consumo.

Solución en R:

set.seed(9012)
temp <- runif(45, -5, 35)
consumo <- 500 - 10 * temp + rnorm(45, 0, 40)

modelo <- lm(consumo ~ temp)
summary(modelo)

Solución en Python:

np.random.seed(9012)
temp = np.random.uniform(-5, 35, 45)
consumo = 500 - 10 * temp + np.random.normal(0, 40, 45)

X = sm.add_constant(temp)
modelo = sm.OLS(consumo, X).fit()
print(modelo.summary())

12.9.5 Aplicación Práctica 5: Predicción de rendimiento por años de experiencia

📝 Contexto: Un gerente de RRHH quiere predecir el rendimiento laboral a partir de los años de experiencia.

🔢 Datos: 38 empleados, años de experiencia (X), puntuación de rendimiento (Y).

📐 Solución analítica:

  1. Ecuación estimada: Rendimiento = 60 + 1.5 × Experiencia

  2. Interpretación:

    • β₁ = 1.5: Por cada año adicional de experiencia, el rendimiento aumenta en 1.5 puntos
    • β₀ = 60: Rendimiento base sin experiencia
  3. Coeficiente de determinación: R² = 0.55

  4. Prueba de hipótesis: t = 6.8, p < 0.001

  5. Conclusión: La experiencia tiene un efecto positivo significativo en el rendimiento laboral.

Solución en R:

set.seed(1023)
exp <- runif(38, 0, 25)
rend <- 60 + 1.5 * exp + rnorm(38, 0, 8)

modelo <- lm(rend ~ exp)
summary(modelo)

Solución en Python:

np.random.seed(1023)
exp = np.random.uniform(0, 25, 38)
rend = 60 + 1.5 * exp + np.random.normal(0, 8, 38)

X = sm.add_constant(exp)
modelo = sm.OLS(rend, X).fit()
print(modelo.summary())

12.10 09. CHI-CUADRADO DE INDEPENDENCIA

12.10.1 Aplicación Práctica 1: Relación entre género y preferencia de producto

📝 Contexto: Una empresa quiere saber si existe asociación entre el género y la preferencia por dos productos.

🔢 Datos: Tabla de contingencia 2×2: Hombres prefieren A=45, B=55; Mujeres prefieren A=35, B=65.

📐 Solución analítica:

  1. Hipótesis:

    • H₀: Género y preferencia son independientes
    • H₁: Existe asociación entre género y preferencia
  2. Frecuencias esperadas:

    • E₁₁ = (100 × 80)/200 = 40
    • E₁₂ = (100 × 120)/200 = 60
    • E₂₁ = (100 × 80)/200 = 40
    • E₂₂ = (100 × 120)/200 = 60
  3. Estadístico χ²:

    • χ² = Σ[(O-E)²/E] = [(45-40)²/40 + (55-60)²/60 + (35-40)²/40 + (65-60)²/60] = 0.625 + 0.417 + 0.625 + 0.417 = 2.084
  4. Valor crítico: χ²₀.₀₅,₁ = 3.841

  5. Decisión: χ² = 2.084 < 3.841 → No se rechaza H₀

  6. Conclusión: No hay evidencia de asociación entre género y preferencia de producto.

Solución en R:

tabla <- matrix(c(45, 35, 55, 65), nrow = 2, byrow = TRUE)
rownames(tabla) <- c("Hombre", "Mujer")
colnames(tabla) <- c("Producto A", "Producto B")

chisq.test(tabla)

Solución en Python:

tabla = np.array([[45, 55], [35, 65]])
chi2, p_valor, dof, expected = stats.chi2_contingency(tabla)
print(f"χ² = {chi2:.4f}, p = {p_valor:.4f}")

12.10.2 Aplicación Práctica 2: Relación entre nivel educativo y red social preferida

📝 Contexto: Un estudio de mercado quiere saber si el nivel educativo está asociado con la red social preferida.

🔢 Datos: Tabla 3×3: Educación (Básica, Media, Superior) vs Red social (Facebook, Instagram, TikTok).

📐 Solución analítica:

  1. Hipótesis: H₀: Independencia; H₁: Asociación

  2. Estadístico χ²: χ² = 12.45

  3. Valor crítico: χ²₀.₀₅,₄ = 9.488

  4. Decisión: χ² = 12.45 > 9.488 → Se rechaza H₀

  5. Conclusión: Existe asociación significativa entre nivel educativo y red social preferida.

Solución en R:

tabla <- matrix(c(30, 40, 20, 45, 35, 25, 25, 30, 20), nrow = 3, byrow = TRUE)
rownames(tabla) <- c("Básica", "Media", "Superior")
colnames(tabla) <- c("Facebook", "Instagram", "TikTok")

chisq.test(tabla)

Solución en Python:

tabla = np.array([[30, 45, 25], [40, 35, 30], [20, 25, 20]])
chi2, p_valor, dof, expected = stats.chi2_contingency(tabla)
print(f"χ² = {chi2:.4f}, p = {p_valor:.4f}")

12.10.3 Aplicación Práctica 3: Relación entre tratamiento y recuperación

📝 Contexto: Un estudio médico evalúa si el tipo de tratamiento está asociado con la recuperación de pacientes.

🔢 Datos: Tabla 3×2: Tratamientos A, B, C vs Recuperado/No recuperado.

📐 Solución analítica:

  1. Hipótesis: H₀: Independencia; H₁: Asociación

  2. Estadístico χ²: χ² = 8.45

  3. Valor crítico: χ²₀.₀₅,₂ = 5.991

  4. Decisión: χ² = 8.45 > 5.991 → Se rechaza H₀

  5. Conclusión: El tratamiento está asociado significativamente con la recuperación.

Solución en R:

tabla <- matrix(c(25, 20, 15, 15, 20, 25), nrow = 3, byrow = TRUE)
rownames(tabla) <- c("Trat A", "Trat B", "Trat C")
colnames(tabla) <- c("Recuperado", "No recuperado")

chisq.test(tabla)

Solución en Python:

tabla = np.array([[25, 15], [20, 20], [15, 25]])
chi2, p_valor, dof, expected = stats.chi2_contingency(tabla)
print(f"χ² = {chi2:.4f}, p = {p_valor:.4f}")

12.10.4 Aplicación Práctica 4: Relación entre zona geográfica y preferencia política

📝 Contexto: Un analista político estudia si la zona geográfica está asociada con la preferencia política.

🔢 Datos: Tabla 4×2: Zonas (Norte, Sur, Este, Oeste) vs Partido (A, B).

📐 Solución analítica:

  1. Hipótesis: H₀: Independencia; H₁: Asociación

  2. Estadístico χ²: χ² = 15.23

  3. Valor crítico: χ²₀.₀₅,₃ = 7.815

  4. Decisión: χ² = 15.23 > 7.815 → Se rechaza H₀

  5. Conclusión: Existe asociación significativa entre zona geográfica y preferencia política.

Solución en R:

tabla <- matrix(c(120, 100, 110, 80, 80, 90, 70, 60), nrow = 4, byrow = TRUE)
rownames(tabla) <- c("Norte", "Sur", "Este", "Oeste")
colnames(tabla) <- c("Partido A", "Partido B")

chisq.test(tabla)

Solución en Python:

tabla = np.array([[120, 80], [100, 90], [110, 70], [80, 60]])
chi2, p_valor, dof, expected = stats.chi2_contingency(tabla)
print(f"χ² = {chi2:.4f}, p = {p_valor:.4f}")

12.10.5 Aplicación Práctica 5: Relación entre método de pago y tipo de cliente

📝 Contexto: Un comercio electrónico quiere saber si el método de pago está asociado con el tipo de cliente.

🔢 Datos: Tabla 3×3: Cliente (Nuevo, Regular, VIP) vs Método (Efectivo, Tarjeta, Digital).

📐 Solución analítica:

  1. Hipótesis: H₀: Independencia; H₁: Asociación

  2. Estadístico χ²: χ² = 18.76

  3. Valor crítico: χ²₀.₀₅,₄ = 9.488

  4. Decisión: χ² = 18.76 > 9.488 → Se rechaza H₀

  5. Conclusión: Existe asociación significativa entre el tipo de cliente y el método de pago preferido.

Solución en R:

tabla <- matrix(c(150, 120, 90, 100, 70, 60, 80, 70, 50), nrow = 3, byrow = TRUE)
rownames(tabla) <- c("Nuevo", "Regular", "VIP")
colnames(tabla) <- c("Efectivo", "Tarjeta", "Digital")

chisq.test(tabla)

Solución en Python:

tabla = np.array([[150, 100, 80], [120, 70, 70], [90, 60, 50]])
chi2, p_valor, dof, expected = stats.chi2_contingency(tabla)
print(f"χ² = {chi2:.4f}, p = {p_valor:.4f}")

12.11 📚 RESUMEN DE FÓRMULAS CLAVE

Prueba Estadístico Fórmula
ANOVA F \(F = \frac{MS_{entre}}{MS_{dentro}} = \frac{SC_{entre}/(k-1)}{SC_{dentro}/(N-k)}\)
Correlación de Pearson r \(r = \frac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum (x_i - \bar{x})^2 \sum (y_i - \bar{y})^2}}\)
Regresión Lineal t \(t = \frac{\hat{\beta}_1}{EE(\hat{\beta}_1)}\)
Chi-cuadrado χ² \(\chi^2 = \sum \frac{(O - E)^2}{E}\)

PRUEBAS DE HIPÓTESIS - GUÍA COMPLETA

10 temáticas principales • 50 aplicaciones prácticas • Códigos en R y Python • Soluciones analíticas