hllinas2023

1 Paquetes

library(MASS)     # mvrnorm function
library(polycor)  # funciones hetcor, polychor, poly.serial, print.polycor 
library(psych)    # tetrachoric, polychoric, biserial and polyserial
library(corrplot) # corrplot function
library(likert)   # escala likertlibrary(knitr)
library(sjPlot)   # data(efc) y para la función plot_likert
library(sjmisc)
library(knitr)
library(kableExtra)
library(dplyr)
library(RColorBrewer) # paleta de colores
library(ggplot2)
library(patchwork)    # para combinar gráficos
library(lsm)

2 Introducción

En los modelos de ecuaciones estructurales (SEM), el insumo principal suele ser una matriz de covarianzas o correlaciones entre las variables observadas. Por eso, es fundamental entender qué mide cada tipo de correlación y en qué situaciones es apropiado usarla. En este capítulo revisamos:

  1. Correlación de Pearson (variables continuas, relación lineal).

  2. Correlación de Spearman (rangos, relaciones monótonas).

  3. Correlación tetracórica (dos variables dicotómicas).

  4. Correlación policórica (dos variables ordinales politómicas).

  5. Visualización de correlaciones mediante heatmaps globales y por grupos.

3 Correlación de Pearson

3.0.1 Definición

Sea \((X,Y)\) un par de variables aleatorias continuas. La correlación de Pearson poblacional se define como

\[ \rho_{XY}\;= \; Corr(X,Y) \;= \; \frac{\mathrm{Cov}(X,Y)}{\sigma_X \sigma_Y} \;= \; \frac{\mathbb{E}\big[(X-\mu_X)(Y-\mu_Y)\big]} {\sqrt{\mathbb{E}(X-\mu_X)^2}\, \sqrt{\mathbb{E}(Y-\mu_Y)^2}}. \]

En una muestra \((x_i,y_i)_{i=1}^n\), el estimador clásico (coeficiente de correlación muestral) es

\[ r_{XY} \;= \; \frac{S_{xy}}{\sqrt{S_{xx}\, S_{yy}}} \;= \; \frac{\displaystyle\sum_{i=1}^{n}(x_i-\bar x)(y_i-\bar y)} {\sqrt{\displaystyle\sum_{i=1}^{n}(x_i-\bar x)^2} \sqrt{\displaystyle\sum_{i=1}^{n}(y_i-\bar y)^2}} \;= \; \frac{\sum\limits_{i=1}^n x_iy_i \,-\, n\,\overline{x}\,\overline{y}}{\sqrt{\left(\sum\limits_{i=1}^n x_i^2 \,-\, n\,\overline{x}^2\right)\left(\sum\limits_{i=1}^n y_i^2 \,-\, n\,\overline{y}^2\right)}} \]

El coeficiente de determinación muestral, simbolizado por \(r^2\), se define como: \[r^2 \;= \; \frac{S_{xy}^2}{S_{xx}\, S_{yy}} \;= \; \frac{SSR}{S_{yy}}\]

3.0.2 Supuestos típicos (muy utilizados en SEM)

  • Relación aproximadamente lineal entre \(X\) y \(Y\).

  • Variables con distribución aproximadamente normal.

  • Ausencia de valores extremos muy influyentes.

3.0.3 Propiedades

Sean \(X\) y \(Y\) dos variables aleatorias cualesquiera (discretas o continuas) con varianzas finitas y positivas y sean \(a, b,c,d\) números reales. Entonces,

  1. \(-1 \leq Corr(X,Y) \leq 1\).

  2. \(Corr(X,Y)=1\) ó \(-1\) si y sólo si existen dos números reales \(m,r\) con \(m\ne 0\), tales que \(Y=mX +r\).

  3. Si \(X\) y \(Y\) son independientes, entonces \(Corr(X,Y)=0\). El recíproco no es cierto, es decir, \(Corr(X,Y)=0\) no implica independencia.

  4. \(Corr(aX+b, cY+d) = Corr(X,Y)\), si \(a\) y \(c\) son ambas positivas o ambas negativas.

Para fines descriptivos, la relación se propone como fuerte si \(|Corr(X,Y)|\geq 0.8\), moderada si \(0.5<|Corr(X,Y)|<0.8\) y débil, si \(|Corr(X,Y)|\leq 0.5\).

4 Pearson: ejemplo 1

4.0.1 Enunciado

La tabla de abajo contiene datos relativos a un anuncio de promoción en 17 revistas. En concreto, estos anuncios promovían el turismo en cierta ciudad e invitaban a los lectores a que escribieran solicitando más información. Las dos variables relacionadas son \(X\) y \(Y\), que representan el costo de la publicidad (en miles de dólares) y la rentabilidad, respectivamente, donde esta última se define como:

\[Y = \frac{\text{Rentabilidad esperada}\,-\, \text{Costo de la publicidad}}{\text{Costo de la publicidad}}.\]

Hállese el coeficiente de correlación muestral e interprétese la respuesta.

#library(knitr)
#library(kableExtra)

df <- data.frame(x = c(1.25, 1.80, 3.10, 1.50, 3.32, 14.67, 16.02, 1.68, 3.07, 
                          2.72, 1.52, 3.81, 4.07, 9.87,  1.61,  2.51, 1.27       
                          ),
                    y = c(106.84, 48.36, 88.31, 78.74, 92.70, 14.41, 24.18, 66.42, 59.06, 
                          121.95, 31.29, 29.73, 17.41, 35.95, 21.93, 22.25, 61.81
                          )
                   )
kable(t(df), caption = "Valores observados de $x$ e $y$") %>%
      kable_styling() %>%
      kable_classic_2(full_width = FALSE)
Table 4.1: Table 4.2: Valores observados de \(x\) e \(y\)
x 1.25 1.80 3.10 1.50 3.32 14.67 16.02 1.68 3.07 2.72 1.52 3.81 4.07 9.87 1.61 2.51 1.27
y 106.84 48.36 88.31 78.74 92.70 14.41 24.18 66.42 59.06 121.95 31.29 29.73 17.41 35.95 21.93 22.25 61.81

4.0.2 Solución

Tenemos que \(\overline{x}=\frac{73.79}{17}=4.3406\) y \(\overline{y}=\frac{921.34}{17}=54.1965\). Por consiguiente,

\[\begin{eqnarray*} r_{XY}&=& \frac{\sum\limits_{i=1}^n x_iy_i \,-\, n\,\overline{x}\,\overline{y}}{\sqrt{\left(\sum\limits_{i=1}^n x_i^2 \,-\, n\,\overline{x}^2\right)\left(\sum\limits_{i=1}^n y_i^2 \,-\, n\,\overline{y}^2\right)}}\\ &=& \frac{2899.7659 \, - \, (17)(4.3406)(54.1965)}{\sqrt{[660.4933 \, - \, (17)(4.3406)^2][68164.143 \,- \, (17)(54.1965)^2]}}\;= \; -0.441 \end{eqnarray*}\]

En forma manual, con este código:

x<-df$x 
y<-df$y

n <- length(x)

# 1. Medias
x_bar <- mean(x)
y_bar <- mean(y)

# 2. Sumatorias necesarias
s_xy   <- sum(x * y)
s_x2   <- sum(x^2)
s_y2   <- sum(y^2)

# 3. Cálculo manual del coeficiente r_XY
num <- s_xy - n * x_bar * y_bar
den <- sqrt( (s_x2 - n * x_bar^2) * (s_y2 - n * y_bar^2) )

r_xy_manual <- num / den

cat("Media de x:", x_bar, "\n")
cat("Media de y:", y_bar, "\n")
cat("Sumatoria de x_i * y_i:", s_xy, "\n")
cat("Sumatoria de x_i^2:", s_x2, "\n")
cat("Sumatoria de y_i^2:", s_y2, "\n")
cat("Coeficiente de correlación r_xy:", r_xy_manual, "\n")

Obtenemos:

## Media de x: 4.340588
## Media de y: 54.19647
## Sumatoria de x_i * y_i: 2899.766
## Sumatoria de x_i^2: 660.4933
## Sumatoria de y_i^2: 68164.14
## Coeficiente de correlación r_xy: -0.4414505

Con esta función, obtenemos directamente el valor de la correlación muestral:

cor.test(x, y)  
## 
##  Pearson's product-moment correlation
## 
## data:  x and y
## t = -1.9054, df = 15, p-value = 0.07607
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.76069114  0.04975036
## sample estimates:
##        cor 
## -0.4414505

La correlación, \(-0.441\), indica que existe una moderada relación negativa entre el costo y la rentabilidad publicitaria de las revistas. Además, el hecho de que el coeficiente de correlación estimado sea negativo, indica que los valores altos del costo tienden a estar asociados con valores bajos de la rentabilidad.

No obstante, como la correlación implica que no hay asociación lineal y un valor de \(-1\) es equivalente a una asociación lineal negativa perfecta, el valor hallado aquí para la correlación muestral no sugiere que haya una asociación extremadamente fuerte entre el costo y la rentabilidad.

5 Pearson: ejemplo 2

5.0.1 Enunciado

En una planta de ensamblaje de semiconductores, un ingeniero investiga la relación entre la resistencia al desprendimiento de un alambre adherido y dos factores: la longitud del alambre y la altura del broquel. En este ejemplo, sólo se considerará uno de los factores, la longitud del alambre. Para esto, se selecciona y se prueba una muestra aleatoria de 25 unidades, observándose la resistencia al desprendimiento del alambre adherido y la longitud del alambre en cada unidad. Los datos se presentan en la Tabla de abajo. Suponiendo que la resistencia al desprendimiento y la longitud del alambre siguen una distribución normal conjunta, hállese la ecuación del modelo de regresión y el coeficiente de determinación e interprétese el resultado.

#library(knitr)
#library(kableExtra)

datos <- data.frame(
           y = c(9.95, 11.66, 24.45, 21.65, 31.75, 17.89, 35.00, 69.00, 25.02, 
                   10.30, 16.86, 34.93, 14.38, 46.59, 9.60, 44.88, 24.35, 54.12, 
                   27.50, 56.63, 17.08, 22.13, 37.00, 21.15, 41.95
                  ),
           x = c(2, 2, 8, 4, 11, 4, 10, 20, 8, 1, 4, 10, 2, 15, 2, 15, 9, 16, 8, 17, 4, 6, 11, 5, 12),
                     
           x_tilde = c(50, 360, 110, 205, 120, 400, 550, 600, 295, 585, 200, 540, 375,
                         250, 52, 290, 100, 510, 300, 590, 412, 100, 400, 400, 500
                         )
                    )
kable(datos,  align = "ccc", col.names = c("y", "x", "x_tilde"),
      caption = "Datos de resistencia (y), longitud codificada (x) y longitud original (x_tilde)") %>%
      kable_styling() %>%
      kable_classic_2(full_width = FALSE)
Table 5.1: Table 5.2: Datos de resistencia (Parte 1)
y x x_tilde
9.95 2 50
11.66 2 360
24.45 8 110
21.65 4 205
31.75 11 120
17.89 4 400
35.00 10 550
69.00 20 600
25.02 8 295
10.30 1 585
16.86 4 200
34.93 10 540
14.38 2 375
Table 5.1: Table 5.1: Datos de resistencia (Parte 2)
y x x_tilde
14 46.59 15 250
15 9.60 2 52
16 44.88 15 290
17 24.35 9 100
18 54.12 16 510
19 27.50 8 300
20 56.63 17 590
21 17.08 4 412
22 22.13 6 100
23 37.00 11 400
24 21.15 5 400
25 41.95 12 500

5.0.2 Solución

Usando los datos de la tabla, pueden calcularse: \[S_{yy}=6105.945, \qquad S_{xx}=698.56, \qquad S_{xy}=2027.713\]

A partir de estos datos, se puede verificar que el modelo de regresión es \(y=5.1145 + 2.9027\) y que el coeficiente de correlación muestral entre \(X\) y \(Y\) es:

\[r \;= \; \frac{S_{xy}}{\sqrt{S_{xx}\, S_{yy}}} \;= \; \frac{2027.713}{\sqrt{(698.56)\,(6105.945)}} \;= \; 0.9818\]

y <- datos$y
x <- datos$x
n <- length(x)

# Medias
y_bar <- mean(y)
x_bar <- mean(x)

# Sumas de cuadrados y productos
Syy <- sum( (y - y_bar)^2 )          # S_yy (total)
Sxx <- sum( (x - x_bar)^2 )
Sxy <- sum( (x - x_bar) * (y - y_bar) )

# Coeficientes de la recta
beta1 <- Sxy / Sxx        # pendiente
beta0 <- y_bar - beta1 * x_bar  # intercepto

# Correlación y coeficiente de determinación
r   <- Sxy / sqrt(Sxx * Syy)
R2  <- r^2

# Mostrar con cat() y descripciones
cat("Media de y (y_bar):", y_bar, "\n")
cat("Media de x (x_bar):", x_bar, "\n")
cat("Suma de cuadrados total Syy:", Syy, "\n")
cat("Suma de cuadrados Sxx:", Sxx, "\n")
cat("Suma de productos Sxy:", Sxy, "\n")
cat("Pendiente beta1:", beta1, "\n")
cat("Intercepto beta0:", beta0, "\n")
cat("Coeficiente de correlacion r:", r, "\n")
cat("Coeficiente de determinacion R^2:", R2, "\n")
## Media de y (y_bar): 29.0328
## Media de x (x_bar): 8.24
## Suma de cuadrados total Syy: 6105.945
## Suma de cuadrados Sxx: 698.56
## Suma de productos Sxy: 2027.713
## Pendiente beta1: 2.902704
## Intercepto beta0: 5.114516
## Coeficiente de correlación r: 0.9818118
## Coeficiente de determinación R^2: 0.9639544

Obsérvese que \(r^2=(0.9818)^2=0.964\) o, con otras palabras, que aproximadamente 96.4% de la variabilidad de la resistencia al desprendimiento está explicada por la relación lineal con la longitud del alambre.

6 Pearson: ejemplo 3

En este ejemplo simulamos dos variables continuas \(X\) y \(Y\), donde sabemos que existe una relación lineal positiva entre ellas. Esto permite ilustrar de manera clara cómo funciona la correlación de Pearson, la prueba de hipótesis asociada y la interpretación de un gráfico de dispersión.

6.0.1 Datos para el ejemplo

set.seed(123)

n  <- 200
x  <- rnorm(n, mean = 0, sd = 1)
y  <- 0.7 * x + rnorm(n, sd = 0.7)   # relación lineal con ruido

6.0.2 Cálculo del coeficiente de correlación de Pearson

# Correlación 
cor(x, y)   # coeficiente de Pearson
## [1] 0.6769254

Este resultado se interpreta así:

  • El valor obtenido es aproximadamente 0.68, lo cual indica una asociación lineal positiva moderada-fuerte entre \(X\) y \(Y\).

  • Cuando \(X\) aumenta, \(Y\) tiende a aumentar.

6.0.3 Gráfico de dispersión con línea de regresión

df <- data.frame(x, y)

ggplot(df, aes(x = x, y = y)) +
  geom_point(color = "#2b83ba", alpha = 0.7, size = 2) +      # puntos
  geom_smooth(method = "lm", se = FALSE, color = "#d7191c",   # recta de regresión
              linewidth = 1.2) +
  labs(
    title = "Correlación de Pearson",
    x = "X",
    y = "Y"
  ) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    panel.grid.major = element_line(color = "grey85"),
    panel.grid.minor = element_blank()
  )

Interpretación visual:

  • Los puntos forman una nube con tendencia ascendente, consistente con el signo positivo del coeficiente de Pearson.

  • La recta ajustada muestra la dirección y fuerza aproximada de la relación.

  • La dispersión alrededor de la recta representa el ruido del modelo \(y=0.7x+ \epsilon\).

7 Pearson: contrastes para la correlación nula

7.0.1 Teorema

Sea \(r\) el coeficiente de correlación muestral, calculado a partir de una muestra aleatoria de \(n\) pares de observaciones de una distribución conjunta normal. Entonces, una prueba de hipótesis con nivel de significancia \(\alpha\) para \(\rho\) es como se presenta en la tabla de abajo, siendo

\[t = \frac{r\cdot\sqrt{n-2}}{\sqrt{1-r^2}}\]

el estadístico de prueba correspondiente y \(t_{\alpha/2}\), el valor de una variable aleatoria, a la derecha del cual se tiene un área de \(\alpha/2\) en la distribución \(t\) de Student con \(n-2\) grados de libertad.

Table 7.1: Table 7.2: Contrastes para ρ (usando la distribución t de Student con n−1 grados de libertad)
Tipo de hipótesis Regla de decisión
H0: ρ ≥ 0 H1: ρ < 0 (Cola a la izquierda |Rechazar H0 si t ≤ −tα; de lo contrario, no rechazar H0.
H0: ρ ≤ 0 H1: ρ > 0 (Cola a la derecha) |Rechazar H0 si t ≥ tα; de lo contrario, no rechazar H0.
H0: ρ = 0 H1: ρ ≠ 0 (Dos colas) |Rechazar H0 si t ≤ −tα/2 o t ≥ tα/2; de lo contrario, no rechazar H

7.0.2 Ejemplo 4

Enunciado.

Un estudio, llevado a cabo por un analista de riesgos políticos, proporcionó puntuaciones medias para la inestabilidad política de 44 países (a mayor puntuación, se considera que el país tiene mayor inestabilidad política). La correlación muestral entre la puntuación obtenida para la inestabilidad política y la inflación de esos países fue 0.43. Contrástese la hipótesis nula de que, en la población, no existe correlación entre la inestabilidad política y la inflación frente a la alternativa de que hay correlación positiva.

Solución.

Denotando por \(\rho\) la correlación poblacional, debemos contrastar:

\[H_0: \rho=0 \qquad \text{frente a} \qquad H_1: \rho>0 ,\]

usando la información muestral \(n=49\) y \(r=0.43\). El contraste se basa en:

\[t \;= \; \frac{r\cdot\sqrt{n-2}}{\sqrt{1-r^2}} \;= \; \frac{0.43\sqrt{49-2}}{\sqrt{1-(0.43)^2}} \;= \; 3.265\]

# Datos del problema
r <- 0.43     # correlación muestral
n <- 49       # tamaño de la muestra

# Estadístico t para prueba H0: rho = 0  vs  H1: rho > 0
t_stat <- r * sqrt(n - 2) / sqrt(1 - r^2)
t_stat
## [1] 3.265216

Como hay \((n-2)=47\) grados de libertad, hallamos que \(t_{0.05}(47)=1.68 < t\) y \(P\)-valor \(=0.001\).

# Valor crítico para prueba unilateral al 5% (cola derecha)
gl <- n-2
t_crit <- qt(1 - 0.05, gl)

# p-valor para prueba unilateral (cola derecha)
p_value <- 1 - pt(t_stat, gl)

# Mostrar con cat()
cat("Valor crítico t_{0.05}(47): ", t_crit, "\n")
cat("P-valor:", p_value, "\n")

Como hay \((n-2)=47\) grados de libertad, hallamos que \(t_{0.05}(47)=1.68 < t\) y \(P\)-valor \(=0.001\).

## Valor crítico t_{0.05}(47):  1.677927
## P-valor: 0.001022356

Por consiguiente, puede rechazarse, al nivel del 5%, la hipótesis nula de que no hay correlación en la población frente a la alternativa de que la verdadera correlación es positiva. Por lo tanto, estos datos contienen fuerte evidencia de que existe asociación (lineal) positiva entre la inflación y las puntuaciones de los expertos sobre la inestabilidad política de los países.

7.0.3 Ejemplo 5

Enunciado.

Reconsidere la situación planteada en el ejemplo 2 y, utilizando los datos de la longitud del alambre que se presentan en la tabla correspondiente, pruebe la hipótesis nula de que que el coeficiente de correlación poblacional es cero contra la alternativa bilateral, todo esto con un nivel de significancia del 5%.

Solución.

Queremos probar la hipótesis \(H_0: \rho=0\) frente a la alternativa \(H_1: \rho\ne 0\). En el ejemplo mencionado encontramos que \(r=0.9818\) y \(r^2=0.96393\). Por lo cual, el valor del estadístico de prueba es:

\[t \;= \; \frac{r\cdot\sqrt{n-2}}{\sqrt{1-r^2}} \;= \; \frac{0.9818\sqrt{25-2}}{\sqrt{1-0.96393}} \;= \; 24.79\]

# Datos del problema
r <- 0.9818     # correlación muestral
n <- 25       # tamaño de la muestra

# Estadístico t para prueba H0: rho = 0  vs  H1: rho > 0
t_stat <- r * sqrt(n - 2) / sqrt(1 - r^2)
t_stat
## [1] 24.79256

Como hay \((n-2)=23\) grados de libertad, hallamos que \(t_{0.025}(23)=2.069 < t\) y \(P\)-valor \(=0\).

## Valor crítico t_{0.025}(47):  2.068658
## P-valor: 0

Por lo tanto, se rechaza \(H_0\) y se concluye que el coeficiente de correlación es distinto de cero. Esto significa que el modelo de regresión poblacional sí es adecuado para ajustar los datos (poblacionales).

8 Pearson: contrastes para la correlación (general)

8.0.1 Teorema

Sea \(r\) el coeficiente de correlación muestral, calculado a partir de una muestra aleatoria de \(n\) pares de observaciones en una distribución conjunta normal. Entonces, una prueba de hipótesis, con nivel de significancia \(\alpha\) para \(\rho\), es como se presenta en la tabla de abajo, siendo

\[Z = \frac{\sqrt{n-3}}{2}\, \ln\left[\frac{(1+r)(1-\rho_0)}{(1-r)(1+\rho_0)}\right], \]

con \(\rho_0\ne 0\), el estadístico de prueba correspondiente y \(Z_{\alpha/2}\), el valor de una variable aleatoria, a la derecha del cual se tiene un área de \(\alpha/2\) en la distribución normal estándar.

Table 8.1: Table 8.2: Contrastes para ρ (usando la distribución t de Student con n−1 grados de libertad)
Tipo de hipótesis Regla de decisión
H0: ρ ≥ 0 H1: ρ < 0 (Cola a la izquierda |Rechazar H0 si Z ≤ −Zα; de lo contrario, no rechazar H0.
H0: ρ ≤ 0 H1: ρ > 0 (Cola a la derecha) |Rechazar H0 si Z ≥ Zα; de lo contrario, no rechazar H0.
H0: ρ = 0 H1: ρ ≠ 0 (Dos colas) |Rechazar H0 si Z ≤ −Zα/2 o t ≥ Zα/2; de lo contrario, no rechazar H

8.0.2 Ejemplo 6

Enunciado.

Un determinado artículo reporta sobre un método de eliminación de nitrógeno, con la intervención, en el tratamiento de materias que flotan en el agua, de un cubo de digestión aeróbica. El nitrógeno total entrante \(x\) (en mg/L) y el porcentaje \(y\) de nitrógeno eliminado fueron registrados durante 20 días, con los siguientes estadísticos de resumen resultantes:

\[\sum x_i=285.90, \quad \sum x_i^2=4409.55, \quad \sum y_i=690.30, \quad \sum y_i^2=29040.29, \quad \sum x_iy_i=10818.56\]

¿Indican los datos que el nitrógeno total entrante y el porcentaje de nitrógeno eliminado están correlacionados positivamente por lo menos en forma moderada (es decir, con una correlación \(\rho\) que satisface \(0.5<\rho<0.8\))? Use \(\alpha=0.05\).

Solución.

Necesitamos probar \(H_0: \rho=0.5\) contra \(H_1:\rho>0.5\). El valor calculado de \(r\) es 0.733.

# Datos resumidos
n       <- 20
sum_x   <- 285.90
sum_x2  <- 4409.55
sum_y   <- 690.30
sum_y2  <- 29040.29
sum_xy  <- 10818.56   

# Cálculo de Sxx, Syy y Sxy
Sxx <- sum_x2 - sum_x^2 / n
Syy <- sum_y2 - sum_y^2 / n
Sxy <- sum_xy - (sum_x * sum_y) / n

# Correlación muestral r
r <- Sxy / sqrt(Sxx * Syy)

# Mostrar resultados
cat("Correlación muestral r: ", r, "\n")
## Correlación muestral r:  0.7330015

Entonces, el valor de prueba es:

\[Z \;= \; \frac{\sqrt{n- 3}}{2}\, \ln\left[\frac{(1+ r)(1-\rho_0)}{(1- r)(1+\rho_0)}\right] \;=\; \frac{\sqrt{20- 3}}{2}\, \ln\left[\frac{(1+ 0.733)(1-0.5)}{(1- 0.733)(1+0.5)}\right] \;= \; 1.59\]

# Hipótesis: H0: rho = 0.5  vs  H1: rho > 0.5
rho0  <- 0.5
Z     <- sqrt(n - 3) / 2 *
         log(((1 + r) * (1 - rho0)) / ((1 - r) * (1 + rho0)))

cat("Estadístico Z:          ", Z, "\n")
## Estadístico Z:           1.591013

Además,

alpha   <- 0.05
z_crit  <- qnorm(1 - alpha)        # valor crítico para prueba unilateral
p_value <- 1 - pnorm(Z)            # p-valor unilateral

cat("Valor crítico z_0.05:   ", z_crit, "\n")
cat("p-valor (cola derecha): ", p_value, "\n")
## Valor crítico z_0.05:    1.644854
## p-valor (cola derecha):  0.05580332

Por lo tanto, en el nivel \(0.05\), no podemos concluir que \(\rho>0.5\). Por lo mismo, no se ha demostrado que la relación sea moderada (conclusión un poco sorprendente porque \(r=0.733\), pero cuando \(n\) es pequeña puede resultar una \(r\) grande aun cuando \(\rho\) sea pequeña).

9 Pearson: intervalo de confianza para la correlación

9.0.1 Teorema

Sea \(r\) el coeficiente de correlación muestral, calculado a partir de una muestra aleatoria de \(n\) pares de observaciones de una distribución conjunta normal. Si se definen

\[\tanh(u) \;= \; \frac{e^u \, - \, e^{-u}}{e^u \, + \, e^{-u}},\quad Z(r)=\frac{1}{2} \ln\Big(\frac{1 + r}{1 - r}\Big)\]

entonces, un intervalo de confianza del \((1-\alpha)100\%\) para \(\rho\) se obtiene mediante:

\[\tanh\left(Z(r) \,-\, \frac{Z_{\alpha/2}}{\sqrt{n-3}}\right) \; < \; \rho\; < \; \tanh\left(Z(r) \,+\, \frac{Z_{\alpha/2}}{\sqrt{n-3}}\right)\]

Aquí, \(Z_{\alpha/2}\) es el valor de una variable aleatoria que deja un área de \(\alpha/2\) a la derecha de la distribución normal estándar. Además, \(Z(r)\) es la llamada transformación de Fisher y es una función que transforma la correlación muestral \(r\) (que está acotada entre \(−1\) y \(1\)) a una variable que es:

  • Aproximadamente normal.

  • No acotada (puede ir de \(-\infty\) a \(+ \infty\)).

  • Con varianza constante, igual a \(1/(n-3)\).

9.0.2 ¿Por qué es necesaria la transformación \(Z(r)\)?

Porque la distribución de la correlación muestral \(r\):

  • No es normal, especialmente cuando \(r\) está lejos de 0.

  • Tiene varianza que depende de \(\rho\).

  • Es sesgada y comprimida cerca de \(-\) y \(1\).

Fisher encontró una función que “estira” los valores y produce una distribución mucho más simétrica y normal. Observe que

  • Si \(r=0\), entonces \(Z(r)=0\).

  • Si \(r\) se acerca a \(1\), \(Z(r)\) crece hacia \(+ \infty\).

  • Si \(r\) se acerca a \(-1\), \(Z(r)\) crece hacia \(- \infty\).

9.0.3 Ejemplo 7: Cálculo de \(Z(r)\) en R

A manera de ejemplo:

r <- c(-0.99, -0.75,  -0.5, 0, 0.5, 0.75, 0.99)
Z <- 0.5 * log((1 + r) / (1 - r))
Z
## [1] -2.6466524 -0.9729551 -0.5493061  0.0000000  0.5493061  0.9729551  2.6466524

R tiene la función atanh(r), que calcula la transformación de Fisher:

atanh(r)
## [1] -2.6466524 -0.9729551 -0.5493061  0.0000000  0.5493061  0.9729551  2.6466524

Graficamente:

#library(ggplot2)

# Secuencia de r (evitando ±1 porque atanh explota)
r_vals <- seq(-0.99, 0.99, length.out = 500)

# Data frame
df <- data.frame(
  r = r_vals,
  Z = atanh(r_vals)
)

# Gráfica con ggplot
ggplot(df, aes(x = r, y = Z)) +
  geom_line(color = "blue", size = 1.2) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray60") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray60") +
  labs(
    title = "Transformación Z de Fisher",
    x = "r (correlación)",
    y = "Z(r) = atanh(r)"
  ) +
  theme_minimal(base_size = 11)

9.0.4 Ejemplo 8

Enunciado.

Considere otra vez la situación planteada en el ejemplo 2 y, utilizando los datos de la longitud del alambre que se presentan en la tabla correspondiente, construya un intervalo del 95% de confianza (aproximado) para \(\rho\).

Solución.

En el ejemplo mencionado encontramos que \(r=0.9818\) y \(r^2=0.96393\). Tenemos que \(Z(r)=\frac{1}{2} \ln\Big(\frac{1 + r}{1 - r}\Big)=2.3452\).

# Datos del ejemplo
n <- 25
r <- 0.9818     # correlación muestral encontrada en el ejemplo

# Transformación z de Fisher
z_r <- 0.5 * log((1 + r) / (1 - r))

# Mostrar resultados
cat("r = ", r, "\n")
cat("z(r) (Fisher) =", z_r, "\n")
## r =  0.9818
## z(r) (Fisher) = 2.34517

Entonces, teniendo en cuenta que \(Z_{0.025}=1.96\), el intervalo pedido es:

\[\tanh\left(2.3452 \,-\, \frac{1.96}{\sqrt{25-3}}\right) \; < \; \rho\; < \; \tanh\left(2.3452 \,+\, \frac{1.96}{\sqrt{25-3}}\right),\]

lo cual se reduce a \(0.9585 <\rho<0.9921\).

# Nivel de confianza 95%
alpha  <- 0.05
z_crit <- qnorm(1 - alpha/2)      # 1.96
se_z   <- 1 / sqrt(n - 3)         # error estándar en escala z

# Límites en escala z
z_inf <- z_r - z_crit * se_z
z_sup <- z_r + z_crit * se_z

# Volver a la escala de correlaciones con tanh
rho_inf <- tanh(z_inf)
rho_sup <- tanh(z_sup)

# Mostrar resultados
cat("z crítico (95%)     =", z_crit, "\n")
cat("Límite inferior z   =", z_inf, "\n")
cat("Límite superior z   =", z_sup, "\n")
cat("IC 95% para rho: (", rho_inf, ",", rho_sup, ")\n")
## z crítico (95%)     = 1.959964
## Límite inferior z   = 1.927304
## Límite superior z   = 2.763035
## IC 95% para rho: ( 0.9585149 , 0.9920684 )

9.0.5 Ejemplo 9

Enunciado.

Reconsidere la situación planteada en el ejemplo 6 y construya un intervalo del 95% de confianza aproximado para \(\rho\).

Solución.

El coeficiente de correlación muestral entre el nitrógeno entrante y el porcentaje de nitrógeno removido fue \(r=0.733\) y \(r^2=0.5373\). Con ello y \(n=20\), \(Z(r)= \frac{1}{2} \ln\Big(\frac{1 + r}{1 - r}\Big)=0.935\).

# Datos del ejemplo
n <- 20
r <- 0.733     # correlación muestral encontrada en el ejemplo

# Transformación z de Fisher
z_r <- 0.5 * log((1 + r) / (1 - r))

# Mostrar resultados
cat("r = ", r, "\n")
cat("z(r) (Fisher) =", z_r, "\n")
## r =  0.733
## z(r) (Fisher) = 0.9351803

Entonces, teniendo en cuenta que \(Z_{0.025}=1.96\), el intervalo pedido es \(0.43 <\rho<0.89\), ya que:

\[\tanh\left(0.935 \,-\, \frac{1.96}{\sqrt{20-3}}\right) \;< \; \rho\; < \; \tanh\left(0.935 \,+\, \frac{1.96}{\sqrt{20-3}}\right),\]

# Nivel de confianza 95%
alpha  <- 0.05
z_crit <- qnorm(1 - alpha/2)      # 1.96
se_z   <- 1 / sqrt(n - 3)         # error estándar en escala z

# Límites en escala z
z_inf <- z_r - z_crit * se_z
z_sup <- z_r + z_crit * se_z

# Volver a la escala de correlaciones con tanh
rho_inf <- tanh(z_inf)
rho_sup <- tanh(z_sup)

# Mostrar resultados
cat("z crítico (95%)     =", z_crit, "\n")
cat("Límite inferior z   =", z_inf, "\n")
cat("Límite superior z   =", z_sup, "\n")
cat("IC 95% para rho: (", rho_inf, ",", rho_sup, ")\n")
## z crítico (95%)     = 1.959964
## Límite inferior z   = 0.4598192
## Límite superior z   = 1.410541
## IC 95% para rho: ( 0.4299369 , 0.887609 )

9.0.6 Ejemplo 10

Consideremos los datos del ejemplo 3. Contrastemos:

\[𝐻_0: \rho = 0 \quad \mbox{versus} \quad H_1: \rho\ne 0\]

# Prueba de hipótesis

cor.test(x, y)                              # Prueba bilateral (defecto: dos colas)
#cor.test(x, y, alternative = "two.sided")  # Prueba bilateral (dos colas)
#cor.test(x, y, alternative = "greater")    # Prueba unilateral (derecha)
#cor.test(x, y, alternative = "less")       # Prueba unilateral (isquierda)
## 
##  Pearson's product-moment correlation
## 
## data:  x and y
## t = 12.941, df = 198, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.5939683 0.7456381
## sample estimates:
##       cor 
## 0.6769254

La salida se interpreta así:

  • El estadístico t es grande en valor absoluto (\(\approx 12.94\)).

  • El p-valor \(\approx 0\), por lo que se rechaza \(H_0\).

  • Hay evidencia estadística muy fuerte de que la correlación poblacional \(\rho\) es distinta de 0.

  • El intervalo de confianza del 95%, aproximadamente \((0.59, 0.75)\), indica una relación lineal positiva clara en la población.

10 Correlación de Spearman

10.0.1 Definición

La correlación de Spearman \(\rho_s\) es la correlación de Pearson aplicada a los rangos de las observaciones. Sean \(R_i = \mathrm{rank}(x_i)\) y \(S_i = \mathrm{rank}(y_i)\) los rangos de \(X\) y \(Y\). Entonces

\[ \rho_s = \mathrm{cor}(R,S). \]

10.0.2 Comentarios (caso sin empates y con empates)

  1. Cuando no hay empates (todos los valores son distintos), la correlación se puede calcular con la fórmula cerrada:

\[ \rho_s = 1 - \frac{6 \displaystyle\sum_{i=1}^{n} d_i^2}{n(n^2-1)}, \quad d_i = R_i - S_i . \]

  1. Si existen empates, se usan rangos promedio y la correlación se calcula aplicando el coeficiente de Pearson sobre esos rangos.

10.0.3 Otros comentarios

Es apropiada cuando:

  • La relación es monótona, pero no necesariamente lineal.

  • Las variables son al menos ordinales.

  • Queremos reducir la influencia de valores extremos (se trabaja con los rangos).

10.0.4 Ejemplo 11: Spearman con relación no lineal

set.seed(123)

x2 <- sort(rnorm(200))
y2 <- exp(x2) + rnorm(200, sd = 0.2)   # relación monótona creciente no lineal

df2 <- data.frame(x2= x2, y2 = y2, x2_rank = rank(x2), y2_rank = rank(y2))

# Correlaciones
cor_pearson  <- cor(x2, y2, method = "pearson")
cor_spearman <- cor(x2, y2, method = "spearman")

cor_pearson
cor_spearman

# Gráfico 1: Visualización extra: datos vs curva exponencial teórica
p1 <- ggplot(df2, aes(x = x2, y = y2)) +
geom_point(color = "#2b83ba", alpha = 0.6, size = 2) +
geom_line(aes(y = exp(x2)), color = "#fdae61", linewidth = 1.2) +
labs(
title = "Observados\n vs curva teórica",
x = "X",
y = "Y"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major = element_line(color = "grey85"),
panel.grid.minor = element_blank()
)

# Gráfico 2: relación no lineal original (Pearson)
p2 <- ggplot(df2, aes(x = x2, y = y2)) +
geom_point(color = "#2b83ba", alpha = 0.7, size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "#d7191c", linewidth = 1) +
labs(
title = paste0("Relación no lineal\n(Pearson = ", round(cor_pearson, 3), ")"),
x = "X",
y = "Y"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major = element_line(color = "grey85"),
panel.grid.minor = element_blank()
)

# Gráfico 3: relación entre rangos (Spearman)
p3 <- ggplot(df2, aes(x = x2_rank, y = y2_rank)) +
geom_point(color = "#1a9850", alpha = 0.7, size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "#d73027", linewidth = 1) +
labs(
title = paste0("Rangos de X e Y\n(Spearman = ", round(cor_spearman, 3), ")"),
x = "Rango(X)",
y = "Rango(Y)"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major = element_line(color = "grey85"),
panel.grid.minor = element_blank()
)

# Mostrar lado a lado
p1 + p2 + p3
## Correlación de Pearson:  0.7528
## Correlación de Spearman: 0.9584

Interpretación de las tres gráficas

Las siguientes gráficas permiten comparar cómo Pearson y Spearman capturan relaciones diferentes entre dos variables, especialmente cuando la relación es monótona pero no lineal.

  1. Gráfico 1: Observados vs curva teórica

    En este panel se muestra la relación real simulada: \[ Y = e^{X} + \varepsilon, \] que es claramente no lineal pero estrictamente monótona creciente. Los puntos (datos observados) siguen muy bien la curva teórica (línea naranja). Esto confirma que existe una relación fuerte entre X y Y, pero no es lineal.

  2. Gráfico 2: Relación no lineal (Pearson = 0.753)

    En este panel graficamos los datos originales y una recta ajustada por regresión lineal. Aunque la relación entre X y Y es fuerte, la recta roja no se ajusta bien, porque Pearson mide únicamente dependencia lineal.

    Por eso, el coeficiente es moderado (0.753) a pesar de que la relación es muy fuerte, solo que no es lineal. Esto muestra una limitación importante del coeficiente de Pearson.

  3. Gráfico 3: Rangos de X e Y (Spearman = 0.958)

    Aquí graficamos los rangos de X contra los rangos de Y. Al aplicar rangos, Spearman mide monotonía, no linealidad. Como X crece y Y también crece consistentemente, los puntos quedan casi alineados, y la recta roja se ajusta muy bien. El resultado es un coeficiente Spearman muy alto (0.958), que refleja fielmente la relación monótona entre X y Y.

Conclusión.

  • Pearson mide alineamiento lineal: falla cuando la relación es curva.

  • Spearman mide alineamiento en rangos: funciona bien siempre que la relación sea monótona, aunque sea no lineal.

Este ejemplo muestra claramente por qué es importante distinguir el tipo de dependencia que queremos medir antes de elegir el coeficiente de correlación.

10.0.5 Ejemplo 12: Caso con empates

En este caso, la fórmula cerrada ya no es correcta. Ahora forzamos empates repitiendo algunos valores.

set.seed(123)

# Creamos datos con empates

x_ties <- c(1, 2, 2, 3, 4, 4, 4, 5, 6, 6)
y_ties <- c(3, 1, 2, 2, 5, 5, 4, 6, 6, 6)

# Rangos (con promedio en empates, que es lo estándar)

Rx_t <- rank(x_ties, ties.method = "average")
Ry_t <- rank(y_ties, ties.method = "average")

df_ties <- data.frame(X = x_ties, y= y_ties, Rx = Rx_t, Ry = Ry_t)

d_t  <- Rx_t - Ry_t
n_t  <- length(x_ties)

# Fórmula cerrada (que asume sin empates)

rho_formula_t <- 1 - (6 * sum(d_t^2)) / (n_t * (n_t^2 - 1))

# Spearman correcto vía cor()

rho_cor_t <- cor(x_ties, y_ties, method = "spearman")

rho_formula_t
rho_cor_t
## Correlación con fórmula:  0.9
## Correlación correcta: 0.8962

Interpretación.

  1. rho_formula_t y rho_cor_t ya no coinciden.

  2. rho_formula_t usa la fórmula que supone rangos \(1,2,\ldots, n\) sin empates. Pero aquí hay valores repetidos, entonces, rangos promediados. Por lo tanto, la fórmula deja de ser exacta.

  3. rho_cor_t es la versión correcta: calcula Pearson sobre los rangos, manejando adecuadamente los empates.

Visualización gráfica.

Las dos gráficas muestran por qué la correlación de Spearman no puede calcularse correctamente usando la fórmula cerrada cuando existen empates en los datos, y por qué es necesario usar la función cor(..., method = "spearman").

# Gráfico en la escala original (con empates)
p4 <- ggplot(df_ties, aes(x = x, y = y)) +
      geom_point(size = 3, alpha = 0.8, color = "#2b83ba") +
      geom_smooth(method = "lm", se = FALSE, color = "#d7191c", linewidth = 1) +
      scale_x_continuous(breaks = sort(unique(x_ties))) +
      scale_y_continuous(breaks = sort(unique(y_ties))) +
      labs(
        title    = "Datos originales\n con empates",
        subtitle = paste0("Spearman (cor) = ", round(rho_cor_t, 3),
                          " \n Fórmula cerrada ≈ ", round(rho_formula_t, 3)),
        x = "X (con empates)",
        y = "Y (con empates)"
      ) +
      theme_minimal(base_size = 11) +
      theme(
        plot.title    = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5)
      )

# Gráfico en la escala de rangos (lo que realmente usa Spearman)
p5 <- ggplot(df_ties, aes(x = Rx, y = Ry)) +
      geom_point(size = 3, alpha = 0.8, color = "#1a9850") +
      geom_smooth(method = "lm", se = FALSE, color = "#d73027", linewidth = 1) +
      scale_x_continuous(breaks = sort(unique(Rx_t))) +
      scale_y_continuous(breaks = sort(unique(Ry_t))) +
      labs(
        title    = "Rangos promediados\n (con empates)",
        subtitle = "Spearman = Pearson aplicado\n a estos rangos",
        x = "Rango(X)",
        y = "Rango(Y)"
      ) +
      theme_minimal(base_size = 11) +
      theme(
        plot.title    = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5)
      )

#Uniendo las gráficas
p4 + p5

Primer gráfico: Datos originales con empates.

En el panel izquierdo se representan los valores originales de \(X\) y \(Y\), donde hay varios empates (valores repetidos). La recta roja corresponde a la regresión lineal sobre los datos originales.

  • La fórmula cerrada de Spearman (que asume rangos 1,2,…,n sin empates) da aproximadamente 0.90.

  • Sin embargo, el valor correcto obtenido mediante cor(..., method = "spearman"), que sí maneja empates mediante rangos promediados, es ligeramente menor: 0.896.

Aunque la diferencia es pequeña en este ejemplo, en bases reales puede ser mayor, especialmente cuando hay muchos empates.

Segundo gráfico: Rangos promediados (lo que realmente usa Spearman).

En el panel derecho se grafican los rangos promediados de \(X\) y \(Y\). Esta es la transformación que realiza Spearman:

\[ \rho_s = \text{cor}\big( \text{rank}(X), \text{rank}(Y) \big) \]

En el caso de empates, los rangos asignados no son enteros consecutivos, sino valores promedio (por ejemplo, si tres observaciones empatan en las posiciones 4, 5 y 6, todas reciben rango 5). La gráfica muestra cómo, aun con empates, la relación sigue siendo altamente monótona y la recta de regresión encaja muy bien. Por eso Spearman funciona correctamente incluso cuando la relación original no es lineal.

En resumen:

  • La fórmula cerrada solo es exacta cuando NO hay empates.

  • Spearman real = correlación de Pearson aplicada a los rangos promediados, manejados automáticamente por cor(..., method = "spearman").

  • Las dos gráficas permiten visualizar la diferencia entre trabajar con valores originales y con rangos, especialmente cuando existen empates.

11 Correlación tetracórica

11.0.1 Preliminares

La correlación tetracórica se utiliza cuando dos variables son dicotómicas, pero se asume que provienen de la dicotomización de variables latentes continuas con distribución normal bivariada.

11.0.2 Definición

Sea \(X^*\) una variable latente continua y \(X\) la versión dicotomizada: \[ X = \begin{cases} 1, & \text{si } X^* > \tau_X,\\ 0, & \text{si } X^* \le \tau_X. \end{cases}, \qquad Y = \begin{cases} 1, & \text{si } Y^* > \tau_Y,\\ 0, & \text{si } Y^* \le \tau_Y. \end{cases} \]

Además, se supone que \((X^*,Y^*)\) son normales estándar bivariadas con correlación poblacional \(\rho\). Aquí \(\tau_X\) y \(\tau_Y\) son los umbrales latentes que determinan dónde se hace el corte entre 0 y 1. Estos umbrales se estiman junto con la correlación tetracórica \(\rho\). Con base en lo anterior, la correlación tetracórica es precisamente ese parámetro \(\rho\) que compatibiliza las probabilidades observadas en la tabla \(2\times 2\), la cual contiene las frecuencias observadas:

\[ \begin{array}{c|cc|c} & X=0 & X=1 & \text{Total} \\ \hline Y=1 & a_{00} & a_{01} & a_{0\cdot} \\ Y=0 & a_{10} & a_{11} & a_{1\cdot} \\ \hline \text{Total} & a_{\cdot0} & a_{\cdot1} & n \\ \end{array} \]

12 Tetracórica: métodos

Presentaremos dos métodos para estimar esta correlación.

12.0.1 Método 1 (aproximación por \(\gamma\))

Un estimador aproximado de la correlación tetracórica está dado por:

\[ \rho = \frac{\gamma - 1}{\gamma + 1}, \]

donde

\[ \gamma = \left( \frac{a_{00} a_{11}}{a_{10} a_{01}} \right)^{\pi/4}, \quad \mbox{si \(a_{ij} > 0\) para todo \(i,j\)} \]

Casos extremos.

  • Si \(a_{10} = 0\) o \(a_{01} = 0\), entonces \(\rho = 1\).

  • Si \(a_{00} = 0\) o \(a_{11} = 0\), entonces \(\rho = -1\).

Varianza del estimador.

La varianza asintótica del estimador \(\rho_z\) (usando la transformación de Fisher) puede aproximarse por:

\[ \sigma^2_z = \left( \frac{\pi\,\gamma}{2(\gamma + 1)^2} \right)^2 \left( \frac{1}{a_{00}} + \frac{1}{a_{01}} + \frac{1}{a_{10}} + \frac{1}{a_{11}} \right). \]

12.0.2 Método 2: basado en la razón de productos \(ad/cb\)

Considere la tabla:

\[ \begin{array}{c|cc} & X=0 & X=1 \\ \hline Y=1 & a & b \\ Y=0 & c & d \\ \end{array} \]

Entonces,

  • Si \(ad > cb\), calculamos el cociente \(R = ad/cb\).

  • Si \(ad < cb\), calculamos \(R = cb/ad\).

De esta forma, siempre \(R \ge 1\). Si

\[ \delta = 1 + \sqrt{R}. \]

entonces, la magnitud de la correlación tetracórica se estima como:

\[ r_t = \cos\!\left(\frac{\pi}{\delta}\right) = \cos\!\left(\frac{\pi}{1+\sqrt{R}}\right). \]

El signo se determina comparando \(ad\) y \(cb\):

  • Si \(ad > cb\), el coeficiente tetracórico es negativo.

  • Si \(ad < cb\), el coeficiente tetracórico es positivo.

13 Tetracórica: probabilidades y densidad normal

En notación de probabilidades, otra forma de expresar la varianza aproximada es

\[ \sigma^2 = \frac{p_0(1-p_0)\,p_1(1-p_1)} {n\,(h_0 h_1)^2}, \]

donde

\[ n = a_{00}+a_{01}+a_{10}+a_{11},\qquad p_0 = \frac{a_{00}+a_{01}}{n},\qquad p_1 = \frac{a_{00}+a_{10}}{n}. \]

Si \(f\) es la función de densidad de la normal estándar y \(\Phi\) su función de distribución acumulada, entonces

\[ h_i = f(z_i), \qquad z_i = \Phi^{-1}(p_i), \]

De modo que:

\[p_i = \mathbb{P}(Z \le z_i) \quad \mbox{para}\quad Z \sim N(0,1)\]

14 Tetracórica: ejemplo 13

14.0.1 Tetracórica: cálculos

En este ejemplo simulamos las dos variables latentes \(X^*\) y \(Y^*\) anteriores con correlación verdadera \(\rho = 0.7\). Primero las dicotomizamos en 0/1 usando el umbral 0 y calculamos la correlación tetracórica a partir de la tabla 2×2.

library(psych) #tetrachoric, polychoric, biserial and polyserial
set.seed(123)

# Matriz de correlación verdadera de latentes
rho_true <- 0.7
Sigma_t  <- matrix(c(1, rho_true, rho_true, 1), nrow = 2)
n  <- 1000
lat <- mvrnorm(n = n, mu = c(0, 0), Sigma = Sigma_t)

# Dicotomización en 0/1 por umbral 0
x_bin <- as.numeric(lat[, 1] > 0)
y_bin <- as.numeric(lat[, 2] > 0)

# Tabla de frecuencias
tab <- table(x_bin, y_bin)
tab

# Cálculo de la tetracórica
tetrach <- tetrachoric(tab)
tetrach

#  Estimacine obtenidas de las correlaciones
cat("Correlación tetracórica estimada:", tetrach$rho, "\n")
cat("Correlación latente verdadera   :", rho_true, "\n")

#Estimaciones de los umbrales
cat("Umbrales para (X*, Y*):", tetrach$tau, "\n")
cat("Umbral para X*:", tetrach$tau[1], "\n")
cat("Umbral para Y*:", tetrach$tau[2], "\n")

La tabla de frecuencias es:

##      y_bin
## x_bin   0   1
##     0 364 137
##     1 125 374

Las correlaciones obtenidas son:

## Correlación latente verdadera   : 0.7
## Correlación tetracórica estimada: 0.6802838

Los umbrales obtenidos son:

## Umbrales para (X*, Y*): 0.002506631 -0.02757641
## Umbral para X*: 0.002506631
## Umbral para Y*: -0.02757641

En la estimación tetracórica, tau representa los umbrales (cortes) de las variables latentes normales que fueron dicotomizadas para producir los valores 0/1 observados. Cada \(\tau\) es el punto tal que:

\[P(X = 1) = P(X^* > \tau)\]

En nuestro ejemplo, los umbrales estimados son aproximadamente 0, lo que indica que las dos variables fueron dicotomizadas alrededor de la mediana de la distribución normal latente, como era esperado.

14.0.2 Tetracórica: visualización

Consideremos los datos del ejemplo anterior y las líneas de código de abajo.

# Data frame para graficar
df_lat <- data.frame(X_star = lat[, 1],
                     Y_star = lat[, 2],
                     X = factor(x_bin, levels = c(0, 1)),
                     Y = factor(y_bin, levels = c(0, 1))
                    )

# Etiqueta de celda (00, 01, 10, 11)
df_lat$cell <- interaction(df_lat$X, df_lat$Y, sep = "")

ggplot(df_lat, aes(x = X_star, y = Y_star, color = cell)) +
    geom_point(alpha = 0.4, size = 1.3) +

# Líneas de corte según los umbrales estimados
    geom_vline(xintercept = tetrach$tau[1], linetype = "dashed", linewidth = 1) +
    geom_hline(yintercept = tetrach$tau[2], linetype = "dashed", linewidth = 1) +
  
    scale_color_manual(values = c("00" = "#4575b4", "01" = "#91bfdb", "10" = "#fee090", "11" = "#fc8d59"),
                       name   = "Celda (X,Y)",
                       labels = c("00", "01", "10", "11")
                      ) +
  
    labs(title = "Variables latentes y dicotomización para la tetracórica",
         subtitle = paste0("ρ latente verdadera = ", rho_true,
         " | ρ tetracórica estimada ≈ ", round(tetrach$rho, 3)),
         x = expression(X^"*"),
         y = expression(Y^"*")
         ) +
        
    theme_minimal(base_size = 11) +
    theme(plot.title    = element_text(face = "bold", hjust = 0.5),
          plot.subtitle = element_text(hjust = 0.5)
         )

La gráfica ilustra de forma clara la lógica detrás de la correlación tetracórica. Las variables observadas \(X\) y \(Y\), codificadas como 0/1, se suponen provenientes de variables latentes continuas \(X^*\) y \(Y^*\), las cuales siguen una distribución normal bivariada.

Cada punto representa un par \((X^*, Y^*)\). Las líneas punteadas corresponden a los umbrales \(\tau_X\) y \(\tau_Y\) que dicotomizan ambas latentes. Estos umbrales dividen el plano en cuatro cuadrantes que generan las categorías observadas:

  • abajo–izquierda: \(X = 0, Y = 0\) (celda 00)

  • abajo–derecha: \(X = 1, Y = 0\) (celda 10)

  • arriba–izquierda: \(X = 0, Y = 1\) (celda 01)

  • arriba–derecha: \(X = 1, Y = 1\) (celda 11)

El color de cada punto indica a cuál celda de la tabla 2×2 pertenece. La densidad observada en cada cuadrante es exactamente lo que determina la tabla de frecuencias, y a partir de ella la función tetrachoric() estima la correlación latente que hace más probable esa partición bajo el modelo bivariado normal.

En este ejemplo, la correlación tetracórica estimada (\(\approx 0.68\)) es muy cercana a la correlación verdadera de las latentes (\(\rho = 0.7\)). Esto confirma que la tetracórica recupera adecuadamente la relación continua subyacente incluso cuando solo observamos las versiones dicotomizadas \(X\) y \(Y\).

15 Correlación policórica

15.0.1 Policórica: definición

La correlación policórica generaliza la idea anterior a dos variables ordinales con más de dos categorías (por ejemplo, ítems tipo Likert). Se asume que existen dos variables latentes normales estándar \(X^*\) y \(Y^*\) con correlación \(\rho\). Cada variable observada se obtiene al aplicar umbrales:

\[ X = \begin{cases} 1 & \text{si } X^* \le \tau_{1} \\ 2 & \text{si } \tau_{1} < X^* \le \tau_{2} \\ \vdots \\ K & \text{si } X^* > \tau_{K-1} \end{cases} \]

y análogamente para \(Y\).

15.0.2 Policórica: Comentarios

  1. La correlación policórica es el parámetro \(\rho\) que hace coincidir las probabilidades de las celdas observadas con las probabilidades del modelo normal bivariado subyacente.

  2. Usualmente se estima por máxima verosimilitud.

  3. En modelos de ecuaciones estructurales (SEM) con ítems ordinales, es común construir la matriz de correlaciones policóricas y usarla como input para una llevar a cabo un análisis factorial confirmatorio (CFA) o un SEM (por ejemplo, con estimador WLSMV).

15.0.3 Policórica: ejemplo 14 (cálculos)

En este ejemplo simulamos dos variables latentes continuas con correlación verdadera \(\rho = 0.5\), y las categorizamos en 4 niveles tipo Likert utilizando umbrales conocidos. Luego calculamos la correlación policórica y, más adelante, visualizamos la dicotomización múltiple.

#library(MASS) #mvrnorm function
#library(polycor) # hetcor, polychor, poly.serial, print.polycor 

set.seed(123)

# Correlación latente verdadera
rho_true_poly <- 0.5
Sigma_p       <- matrix(c(1, rho_true_poly,
                          rho_true_poly, 1), nrow = 2)

n  <- 1000
lat2 <- mvrnorm(n = n, mu = c(0, 0), Sigma = Sigma_p)

# Definimos umbrales para construir 4 categorías Likert
cuts <- qnorm(c(0.2, 0.5, 0.8))

x_ord <- cut(lat2[, 1],
             breaks = c(-Inf, cuts, Inf),
             labels = 1:4,
             ordered_result = TRUE)

y_ord <- cut(lat2[, 2],
             breaks = c(-Inf, cuts, Inf),
             labels = 1:4,
             ordered_result = TRUE)

# Tabla de contingencia
tab_ord <- table(x_ord, y_ord)
tab_ord

# Correlación policórica
poly <- polychor(tab_ord)
poly

# Umbrales verdaderos de la simulación
cat("Correlación policórica estimada:", poly, "\n")
cat("Correlación latente verdadera   :", rho_true_poly, "\n")

La tabla de frecuencia es:

##      y_ord
## x_ord   1   2   3   4
##     1  88  73  27  10
##     2  66 103 111  39
##     3  32  88 100  72
##     4   8  34  71  78

Esta tabla muestra cómo se distribuyen las observaciones en las combinaciones ordinales \((X,Y)\) después de aplicar los umbrales a las variables latentes. Cada celda refleja cuántos individuos cayeron en una determinada categoría de \(X\) y \(Y\). Esta distribución es la base del cálculo de la correlación policórica: el estimador busca la correlación latente que hace más probable esta tabla, bajo el supuesto de que las variables originales eran continuas y normalmente distribuidas.

Las correlaciones obtenidas son:

## Correlación latente verdadera   : 0.5
## Correlación policórica estimada: 0.4883425

En este caso, la correlación latente verdadera utilizada en la simulación fue \(\rho = 0.5\), y la correlación policórica estimada resulta muy cercana (\(\hat{\rho} \approx 0.488\)). Esto indica que el método policórico recupera de manera adecuada la dependencia subyacente entre las variables continuas, incluso cuando solo observamos sus versiones ordinales discretizadas.

Comentario adicional sobre los umbrales.

En la simulación, definimos explícitamente los umbrales de las variables latentes. El estimador policórico trata de recuperar una correlación latente coherente con estos cortes. Aunque polychor(tab_ord) no devuelve los umbrales tau, podemos aproximarlos a partir de las proporciones marginales, porque en el modelo latente:

\[ \tau_j \approx \Phi^{-1}\big( P(X \le j) \big) \]

donde \(\Phi^{-1}\) es la inversa de la normal estándar. Con R se pueden hallar así:

# 2) Umbrales estimados a partir de las proporciones marginales
prop_x <- prop.table(margin.table(tab_ord, 1))
prop_y <- prop.table(margin.table(tab_ord, 2))

cum_x <- cumsum(prop_x)
cum_y <- cumsum(prop_y)

tau_x_hat <- qnorm(cum_x[-length(cum_x)])
tau_y_hat <- qnorm(cum_y[-length(cum_y)])

cat("Umbrales estimados a partir de la tabla (aprox.):\n")
cat("  tau_X* =", round(tau_x_hat, 4), "\n")
cat("  tau_Y* =", round(tau_y_hat, 4), "\n")

Los umbrales estimados a partir de la tabla (aprox.) son:

##   tau_X* = -0.8488 0.0426 0.8742
##   tau_Y* = -0.8633 -0.0201 0.8452

15.0.4 Policórica: visualización gráfica

Considere los datos anteriores. Una vez calculada la correlación policórica, ahora, visualizamos la dicotomización múltiple.

library(ggplot2)

df_poly <- data.frame(X_star = lat2[,1],
                      Y_star = lat2[,2],
                      X = x_ord,
                      Y = y_ord
                      )

# Cada punto se colorea según la combinación ordinal (1–4 × 1–4)
df_poly$cell <- interaction(df_poly$X, df_poly$Y, sep="-")

ggplot(df_poly, aes(x = X_star, y = Y_star, color = cell)) +
      geom_point(alpha = 0.4, size = 1.2) +

# Líneas verticales (umbrales de X*)
      geom_vline(xintercept = cuts, linetype = "dashed", linewidth = 1) +

# Líneas horizontales (umbrales de Y*)
      geom_hline(yintercept = cuts, linetype = "dashed", linewidth = 1) +
      
      scale_color_viridis_d(name = "Categorías (X,Y)") +
  
      labs(title = "Variables latentes y categorización\n ordinal para la policórica",
          subtitle = paste0("ρ latente = 0.5 | ρ policórica estimada ≈ ", round(poly, 3)),
          x = expression(X^"*"),
          y = expression(Y^"*")
          ) +
  
      theme_minimal(base_size = 11) +
      theme(plot.title    = element_text(face="bold",hjust=0.5),
            plot.subtitle = element_text(hjust=0.5)
            )

La gráfica ilustra el fundamento de la correlación policórica, que estima la relación entre dos variables latentes continuas \(X^*\) y \(Y^*\) cuando solo observamos sus versiones ordinales. Los puntos representan los valores latentes, simulados desde una distribución normal bivariada con correlación verdadera \(\rho = 0.5\).

Las líneas punteadas verticales y horizontales son los umbrales que dividen cada latente en cuatro categorías ordinales tipo Likert (1–4). Estos cortes generan una partición del plano en 16 rectángulos, cada uno correspondiente a una combinación \((X,Y)\). Los colores indican la categoría conjunta, permitiendo ver cómo la distribución de puntos en cada región determina la tabla de contingencia ordinal.

La función polychor() estima la correlación latente que hace más probable esta partición bajo el modelo normal bivariado. En este ejemplo, el valor policórico estimado (≈ 0.49) se aproxima a la correlación latente verdadera (0.5), mostrando que la policórica recupera adecuadamente la relación continua subyacente aun cuando la información observable está discretizada en cuatro niveles.

16 Matrices de correlaciones mixtas

En modelos de ecuaciones estructurales (SEM) con variables de distintos tipos:

  • Continuas,

  • Ordinales tipo Likert,

  • Dicotómicas,

es una práctica recomendada construir una matriz de correlaciones mixta:

  • Pearson para continuas.

  • Tetracórica para dicotómicas.

  • Policórica para ordinales.

El paquete psych provee la función mixedCor() que realiza esto automáticamente.

17 Correlaciones mixtas: ejemplo 15

17.0.1 Datos simulados con variables de distintos tipos

Simulamos:

  • 3 variables continuas

  • 2 ordinales (4 niveles)

  • 2 dicotómicas

set.seed(123)

n <- 500

# 1) Variables latentes continuas correlacionadas
Sigma_m <- matrix(c(
  1,   0.5, 0.4,
  0.5, 1,   0.3,
  0.4, 0.3, 1
), nrow = 3, byrow = TRUE)

latent <- mvrnorm(n, mu = c(0, 0, 0), Sigma = Sigma_m)

cont1 <- latent[, 1]
cont2 <- latent[, 2]
cont3 <- latent[, 3]

# 2) Ordinales (4 niveles)
cuts_m <- qnorm(c(0.25, 0.5, 0.75))

ord1_fac <- cut(latent[,1], breaks = c(-Inf, cuts_m, Inf),
                labels = 1:4, ordered_result = TRUE)
ord2_fac <- cut(latent[,2], breaks = c(-Inf, cuts_m, Inf),
                labels = 1:4, ordered_result = TRUE)

# Para mixedCor las codificamos como numéricas 1,2,3,4
ord1 <- as.numeric(ord1_fac)
ord2 <- as.numeric(ord2_fac)

# 3) Dicotómicas (0/1)
bin1 <- as.numeric(latent[,1] > 0)
bin2 <- as.numeric(latent[,2] > 0)

# Data frame final (solo variables que entran a la matriz mixta)
df_mixed <- data.frame(cont1, cont2, cont3, ord1, ord2, bin1, bin2)

# Variable categórica de grupo para los ejemplos por subgrupos
grupo <- sample(c("A", "B"), size = n, replace = TRUE)
df_mixed$grupo <- factor(grupo)

str(df_mixed)

Una parte del data frame es:

##        cont1      cont2      cont3 ord1 ord2 bin1 bin2 grupo
## 1 -0.9101540  0.2556358 -0.6399185    1    3    0    1     B
## 2 -0.6013915  0.7151146 -0.6688456    2    4    0    1     A
## 3  1.1446115  0.7449064  1.8091561    4    4    1    1     B
## 4 -0.1192797 -0.2414153  0.5888746    2    2    0    0     B
## 5 -1.0282848  1.8614412 -0.5127555    1    4    0    1     A
## 6  1.9984530  0.9536554  0.9675106    4    4    1    1     B

El cual tiene la sguiente estructura:

## 'data.frame':    500 obs. of  8 variables:
##  $ cont1: num  -0.91 -0.601 1.145 -0.119 -1.028 ...
##  $ cont2: num  0.256 0.715 0.745 -0.241 1.861 ...
##  $ cont3: num  -0.64 -0.669 1.809 0.589 -0.513 ...
##  $ ord1 : num  1 2 4 2 1 4 3 3 2 2 ...
##  $ ord2 : num  3 4 4 2 4 4 4 1 1 2 ...
##  $ bin1 : num  0 0 1 0 0 1 1 1 0 0 ...
##  $ bin2 : num  1 1 1 0 1 1 1 0 0 0 ...
##  $ grupo: Factor w/ 2 levels "A","B": 2 1 2 2 1 2 1 1 1 2 ...

17.0.2 Matriz mixta global

# columnas 1:3 = continuas, 4:5 = ordinales, 6:7 = dicotómicas
mixed <- mixedCor(df_mixed[, 1:7],
                  c = 1:3,    # continuous
                  p = 4:5,    # polytomous ordinal
                  d = 6:7)    # dichotomous

R <- mixed$rho  # matriz de correlaciones mixtas

#Tabla de correlaciones
kable(R, digits = 3,
      caption = "Matriz de Correlaciones Mixtas (Pearson + Policórica + Tetracórica)") %>%
  kable_styling() %>%
  kable_classic_2(full_width = FALSE)
Table 17.1: Table 17.2: Matriz de Correlaciones Mixtas (Pearson + Policórica + Tetracórica)
cont1 cont2 cont3 ord1 ord2 bin1 bin2
cont1 1.000 0.489 0.392 0.998 0.507 0.993 0.536
cont2 0.489 1.000 0.229 0.483 1.000 0.506 1.000
cont3 0.392 0.229 1.000 0.396 0.250 0.365 0.291
ord1 0.998 0.483 0.396 1.000 0.488 1.000 0.535
ord2 0.507 1.000 0.250 0.488 1.000 0.523 1.000
bin1 0.993 0.506 0.365 1.000 0.523 1.000 0.563
bin2 0.536 1.000 0.291 0.535 1.000 0.563 1.000

18 Heatmaps de correlaciones

En análisis exploratorio y en SEM es muy útil visualizar la matriz de correlaciones como un heatmap:

  • Global (toda la muestra).

  • Separado por niveles de una variable categórica, para comparar patrones de correlación entre grupos.

18.0.1 Heatmap global de correlaciones mixtas

#library(corrplot)  #corrplot function

corrplot(R, method = "color",
         tl.col = "black", tl.cex = .8,
         title = "Matriz de correlación mixta (global)",
         mar = c(0,0,2,0))

18.0.2 Heatmaps por grupo (variable categórica)

Ahora calculamos la matriz de correlaciones mixtas por grupo (por ejemplo, grupo A vs grupo B) y dibujamos un heatmap para cada uno.

# Función auxiliar para obtener matriz mixta por grupo
get_mixed_cor <- function(data){
  mixedCor(data[, 1:7])$rho
}

R_A <- df_mixed %>%
  filter(grupo == "A") %>%
  get_mixed_cor()

R_B <- df_mixed %>%
  filter(grupo == "B") %>%
  get_mixed_cor()

par(mfrow = c(1, 2))
corrplot(R_A, method = "color",
         tl.col = "black", tl.cex = .8,
         title = "Correlaciones mixtas - Grupo A",
         mar = c(0,0,2,0))

corrplot(R_B, method = "color",
         tl.col = "black", tl.cex = .8,
         title = "Correlaciones mixtas - Grupo B",
         mar = c(0,0,2,0))
par(mfrow = c(1, 1))

Estos gráficos permiten comparar visualmente si las relaciones entre variables son similares o diferentes según el grupo definido por la variable categórica (por ejemplo, sexo, tipo de institución, tratamiento/control, etc.).

19 Ejemplo 16: likert y heatmaps

En esta sección usamos datos reales para ilustrar:

  1. Qué es una escala tipo Likert.

  2. Cómo interpretar las opciones de respuesta.

  3. Qué representan los ítems del COPE-Index en el dataset efc.

  4. Cómo visualizar los ítems con un gráfico Likert.

  5. Cómo calcular correlaciones policóricas.

  6. Cómo construir heatmaps globales y heatmaps por grupos.

19.0.1 Escala tipo Likert

Una escala tipo Likert es un conjunto de ítems donde cada respuesta expresa el grado de acuerdo, frecuencia, intensidad o percepción respecto a una afirmación.

Usaremos el conjunto de datos efc, incluido en el paquete sjPlot. Este conjunto proviene del estudio EUROFAMCARE e incluye, entre otros, varios ítems del COPE-Index, que miden la carga y experiencia del cuidador en escala tipo Likert. En este dataset, los ítems siguen la siguiente escala ordinal de 1 a4:

Valor Significado general (Likert)
1 Nunca / Muy en desacuerdo / Casi nunca
2 A veces / En desacuerdo
3 A menudo / De acuerdo
4 Siempre / Muy de acuerdo / Con mucha frecuencia

Estas categorías son ordinales (\(1 < 2 < 3 < 4\)), pero no representan una distancia numérica exacta.

19.0.2 Variables cop\_* del COPE-Index

El COPE-Index es un instrumento internacional que evalúa:

  • Carga del cuidador.

  • Experiencias subjetivas.

  • Calidad del apoyo.

  • Relación con la persona cuidada.

19.0.3 Los datos

#library(dplyr)
library(sjPlot) # para data(efc)
#library(sjmisc)

# Cargamos los datos de ejemplo
data(efc)
datos <- efc
head(datos)
##   c12hour e15relat e16sex e17age e42dep c82cop1 c83cop2 c84cop3 c85cop4 c86cop5
## 1      16        2      2     83      3       3       2       2       2       1
## 2     148        2      2     88      3       3       3       3       3       4
## 3      70        1      2     82      3       2       2       1       4       1
## 4     168        1      2     67      4       4       1       3       1       1
## 5     168        2      2     84      4       3       2       1       2       2
## 6      16        2      2     85      4       2       2       3       3       3
##   c87cop6 c88cop7 c89cop8 c90cop9 c160age c161sex c172code c175empl barthtot
## 1       1       2       3       3      56       2        2        1       75
## 2       1       3       2       2      54       2        2        1       75
## 3       1       1       4       3      80       1        1        0       35
## 4       1       1       2       4      69       1        2        0        0
## 5       2       1       4       4      47       2        2        0       25
## 6       2       2       1       1      56       1        2        1       60
##   neg_c_7 pos_v_4 quol_5 resttotn tot_sc_e n4pstu nur_pst
## 1      12      12     14        0        4      0      NA
## 2      20      11     10        4        0      0      NA
## 3      11      13      7        0        1      2       2
## 4      10      15     12        2        0      3       3
## 5      12      15     19        2        1      2       2
## 6      19       9      8        1        3      2       2
names(datos)
##  [1] "c12hour"  "e15relat" "e16sex"   "e17age"   "e42dep"   "c82cop1" 
##  [7] "c83cop2"  "c84cop3"  "c85cop4"  "c86cop5"  "c87cop6"  "c88cop7" 
## [13] "c89cop8"  "c90cop9"  "c160age"  "c161sex"  "c172code" "c175empl"
## [19] "barthtot" "neg_c_7"  "pos_v_4"  "quol_5"   "resttotn" "tot_sc_e"
## [25] "n4pstu"   "nur_pst"

19.0.4 Selección de ítems tipo Likert (COPE-Index)

Identificamos los ítems del COPE-Index tienen la cadena cop en el nombre de la variable:

find_var(datos, pattern = "cop")

Esto devuelve algo como:

cop1:  do you feel you cope well as caregiver?
  
cop2:  do you find caregiving too demanding?
  
cop3:  does caregiving cause difficulties in your relationship with your friends?
  
cop4:  does caregiving have negative effect on your physical health?
  
cop5:  does caregiving cause difficulties in your relationship with your family?
  
cop6:  does caregiving cause financial difficulties?
  
cop7:  do you feel trapped in your role as caregiver?
  
cop8:  do you feel supported by friends/neighbours?
  
cop9:  do you feel caregiving worthwhile?

En español:

  • cop1: ¿Siente que afronta bien su labor como cuidador?

  • cop2: ¿Considera que la labor de cuidado es demasiado exigente?

  • cop3: ¿El cuidado genera dificultades en su relación con sus amigos?

  • cop4: ¿El cuidado tiene un efecto negativo en su salud física?

  • cop5: ¿El rol de cuidador le causa dificultades en su relación con su familia?

  • cop6: ¿El cuidado le genera dificultades financieras?

  • cop7: ¿Siente que está atrapado en su rol como cuidador?

  • cop8: ¿Siente que recibe apoyo de amigos o vecinos?

  • cop9: ¿Considera que la labor de cuidado vale la pena?

El data frame correspondiente es:

mydf <- find_var(datos, pattern = "cop", out = "df")
head(mydf)
##   c82cop1 c83cop2 c84cop3 c85cop4 c86cop5 c87cop6 c88cop7 c89cop8 c90cop9
## 1       3       2       2       2       1       1       2       3       3
## 2       3       3       3       3       4       1       3       2       2
## 3       2       2       1       4       1       1       1       4       3
## 4       4       1       3       1       1       1       1       2       4
## 5       3       2       1       2       2       2       1       4       4
## 6       2       2       3       3       3       2       2       1       1

19.0.5 Gráfico Likert: Visualizando las opciones de respuesta

En esta sección se muestra cómo preparar variables tipo Likert para su análisis utilizando los paquetes sjmisc, sjPLot y likert. El objetivo es:

  1. Convertir los ítems en factores ordenados (categorías 1–4).

  2. Crear un objeto de clase likert.

  3. Obtener resúmenes numéricos.s con un gráfico de barras apiladas (cuando sea posible).

Con el paquete sjmisc

El paquete contiene la función frq(), que produce: frecuencias absolutas, porcentajes, valores válidos, valores perdidos y distribución etiquetada.

library(sjmisc)

# Tabla completa de frecuencias para todos los ítems
frq(mydf)
## do you feel you cope well as caregiver? (c82cop1) <numeric> 
## # total N=908 valid N=901 mean=3.12 sd=0.58
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     never |   3 |  0.33 |    0.33 |   0.33
##     2 | sometimes |  97 | 10.68 |   10.77 |  11.10
##     3 |     often | 591 | 65.09 |   65.59 |  76.69
##     4 |    always | 210 | 23.13 |   23.31 | 100.00
##  <NA> |      <NA> |   7 |  0.77 |    <NA> |   <NA>
## 
## do you find caregiving too demanding? (c83cop2) <numeric> 
## # total N=908 valid N=902 mean=2.02 sd=0.72
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     Never | 186 | 20.48 |   20.62 |  20.62
##     2 | Sometimes | 547 | 60.24 |   60.64 |  81.26
##     3 |     Often | 130 | 14.32 |   14.41 |  95.68
##     4 |    Always |  39 |  4.30 |    4.32 | 100.00
##  <NA> |      <NA> |   6 |  0.66 |    <NA> |   <NA>
## 
## does caregiving cause difficulties in your relationship with your friends? (c84cop3) <numeric> 
## # total N=908 valid N=902 mean=1.63 sd=0.87
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     Never | 516 | 56.83 |   57.21 |  57.21
##     2 | Sometimes | 252 | 27.75 |   27.94 |  85.14
##     3 |     Often |  82 |  9.03 |    9.09 |  94.24
##     4 |    Always |  52 |  5.73 |    5.76 | 100.00
##  <NA> |      <NA> |   6 |  0.66 |    <NA> |   <NA>
## 
## does caregiving have negative effect on your physical health? (c85cop4) <numeric> 
## # total N=908 valid N=898 mean=1.77 sd=0.87
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     Never | 409 | 45.04 |   45.55 |  45.55
##     2 | Sometimes | 346 | 38.11 |   38.53 |  84.08
##     3 |     Often |  85 |  9.36 |    9.47 |  93.54
##     4 |    Always |  58 |  6.39 |    6.46 | 100.00
##  <NA> |      <NA> |  10 |  1.10 |    <NA> |   <NA>
## 
## does caregiving cause difficulties in your relationship with your family? (c86cop5) <numeric> 
## # total N=908 valid N=902 mean=1.39 sd=0.67
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     Never | 626 | 68.94 |   69.40 |  69.40
##     2 | Sometimes | 211 | 23.24 |   23.39 |  92.79
##     3 |     Often |  50 |  5.51 |    5.54 |  98.34
##     4 |    Always |  15 |  1.65 |    1.66 | 100.00
##  <NA> |      <NA> |   6 |  0.66 |    <NA> |   <NA>
## 
## does caregiving cause financial difficulties? (c87cop6) <numeric> 
## # total N=908 valid N=900 mean=1.29 sd=0.64
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     Never | 713 | 78.52 |   79.22 |  79.22
##     2 | Sometimes | 131 | 14.43 |   14.56 |  93.78
##     3 |     Often |  39 |  4.30 |    4.33 |  98.11
##     4 |    Always |  17 |  1.87 |    1.89 | 100.00
##  <NA> |      <NA> |   8 |  0.88 |    <NA> |   <NA>
## 
## do you feel trapped in your role as caregiver? (c88cop7) <numeric> 
## # total N=908 valid N=900 mean=1.92 sd=0.91
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     Never | 336 | 37.00 |   37.33 |  37.33
##     2 | Sometimes | 374 | 41.19 |   41.56 |  78.89
##     3 |     Often | 113 | 12.44 |   12.56 |  91.44
##     4 |    Always |  77 |  8.48 |    8.56 | 100.00
##  <NA> |      <NA> |   8 |  0.88 |    <NA> |   <NA>
## 
## do you feel supported by friends/neighbours? (c89cop8) <numeric> 
## # total N=908 valid N=901 mean=2.16 sd=1.04
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     never | 313 | 34.47 |   34.74 |  34.74
##     2 | sometimes | 237 | 26.10 |   26.30 |  61.04
##     3 |     often | 241 | 26.54 |   26.75 |  87.79
##     4 |    always | 110 | 12.11 |   12.21 | 100.00
##  <NA> |      <NA> |   7 |  0.77 |    <NA> |   <NA>
## 
## do you feel caregiving worthwhile? (c90cop9) <numeric> 
## # total N=908 valid N=888 mean=2.93 sd=0.96
## 
## Value |     Label |   N | Raw % | Valid % | Cum. %
## --------------------------------------------------
##     1 |     never |  76 |  8.37 |    8.56 |   8.56
##     2 | sometimes | 210 | 23.13 |   23.65 |  32.21
##     3 |     often | 300 | 33.04 |   33.78 |  65.99
##     4 |    always | 302 | 33.26 |   34.01 | 100.00
##  <NA> |      <NA> |  20 |  2.20 |    <NA> |   <NA>

Con el paquete sjPLot

El paquete sjPlot incluye la función plot_likert(), que permite generar gráficos tipo Likert de manera rápida y con un diseño limpio. Esta función produce barras horizontales apiladas que representan la distribución de frecuencias en cada categoría de respuesta para todos los ítems incluidos en el data frame. Se resalta que eel paquete sjPlot está orientado principalmente a visualización, no a generar tablas de frecuencias como objeto numérico. Para ello, el ecosistema sj incorpora funciones complementarias en el paquete sjmisc, especialmente frq(), que permiten obtener tablas de frecuencias completas para ítems Likert.

#library(sjPlot)  # para la función plot_likert

plot_likert(
mydf,
title        = "Distribuciones de las respuestas Likert (COPE-Index)",
legend.title = "Nivel de respuesta",
wrap.labels  = 30, 
values = "none"
)

Con el paquete likert

#library(likert)
#library(RColorBrewer) # paletas de colores

# Paso 1. Convertir todas las columnas a factores ordenados 1–4
datosP <- mydf %>%
  mutate(across(everything(), ~ factor(., levels = 1:4, ordered = TRUE))) %>%
  as.data.frame()

# Paso 2. Crear objeto tipo likert
lik <- likert(datosP)

lik$results %>%  mutate_if(is.numeric, round, digits=2) 

# Paso 3. Revisar un resumen rápido
summary(lik)%>%   mutate_if(is.numeric, round, digits=2) 

# Paso 4. Gráfico tipo Likert en barras
plot(lik, type="bar") +
  scale_fill_manual(values = brewer.pal(n=4,"Blues"))

Paso 1. El primer paso consiste en transformar todas las columnas del data frame mydf en factores ordenados, especificando explícitamente los niveles 1, 2, 3 y 4. En este sentido, datosP será un data frame donde cada ítem está declarado como variable ordinal, listo para usar con el paquete likert.

Paso 2. La función likert() toma un data frame de variables ordinales y calcula la distribución porcentual de respuestas por categoría para cada ítem. En este sentido, likert(datosP) crea un objeto de clase likert, que resume Una tabla descriptiva de distribución de respuestas por ítem, que el paquete usa después para los gráficos.

Item 1 2 3 4
c82cop1 0.33 10.77 65.59 23.31
c83cop2 20.62 60.64 14.41 4.32
c84cop3 57.21 27.94 9.09 5.76
c85cop4 45.55 38.53 9.47 6.46
c86cop5 69.40 23.39 5.54 1.66
c87cop6 79.22 14.56 4.33 1.89
c88cop7 37.33 41.56 12.56 8.56
c89cop8 34.74 26.30 26.75 12.21
c90cop9 8.56 23.65 33.78 34.01

Paso 3. El método summary(lik) genera estadísticas adicionales, útiles para comparar los ítems entre sí. Este resumen incluye:

  • low: porcentaje de respuestas en categorías bajas

  • neutral: categoría central (en escalas 1–5; en 1–4 puede ser 0)

  • high: porcentaje en categorías altas

  • mean: media de la escala tratada como numérica

  • sd: dispersión de las respuestas

Item low neutral high mean sd
1 c82cop1 11.10 0 88.90 3.12 0.58
9 c90cop9 32.21 0 67.79 2.93 0.96
8 c89cop8 61.04 0 38.96 2.16 1.04
7 c88cop7 78.89 0 21.11 1.92 0.91
2 c83cop2 81.26 0 18.74 2.02 0.72
4 c85cop4 84.08 0 15.92 1.77 0.87
3 c84cop3 85.14 0 14.86 1.63 0.87
5 c86cop5 92.79 0 7.21 1.39 0.67
6 c87cop6 93.78 0 6.22 1.29 0.64

Paso 4. Finalmente, se construye un gráfico para visualizar de manera intuitiva las distribuciones de los ítems.

  • plot(lik, type="bar") genera un gráfico estándar de barras apiladas.

  • Las barras se centran en cero para separar categorías bajas y altas.

  • scale_fill_manual() ajusta la paleta de colores para las cuatro categorías.

Este gráfico permite observar:

  • Qué ítems tienen mayor concentración de respuestas en valores altos,

  • Cuáles muestran mayor desacuerdo o valores bajos,

  • Comparaciones rápidas entre todos los ítems del COPE-Index.

19.0.6 Correlaciones: con polychoric()

La función polychoric() del paquete psych estima la correlación policórica, es decir, la correlación entre variables latentes continuas normales que han sido observadas como variables ordinales (por ejemplo, ítems Likert). Al aplicarla se obtiene un objeto lista con dos matrices principales, cada una con los siguientes componentes: correlaciones policóricas y umbrales (thresholds).

poly_res <- polychoric(mydf)
poly_res

# Matriz de correlaciones policóricas
R_likert <- poly_res$rho
R_likert

# Matrices de umbrales (thresholds)
tau_likert <- poly_res$tau
tau_likert
## Call: polychoric(x = mydf)
## Polychoric correlations 
##         c82c1 c83c2 c84c3 c85c4 c86c5 c87c6 c88c7 c89c8 c90c9
## c82cop1  1.00                                                
## c83cop2 -0.50  1.00                                          
## c84cop3 -0.30  0.47  1.00                                    
## c85cop4 -0.35  0.55  0.50  1.00                              
## c86cop5 -0.23  0.36  0.47  0.41  1.00                        
## c87cop6 -0.18  0.41  0.46  0.54  0.44  1.00                  
## c88cop7 -0.46  0.62  0.58  0.52  0.43  0.46  1.00            
## c89cop8  0.16 -0.14 -0.18 -0.10 -0.10 -0.01 -0.17  1.00      
## c90cop9  0.37 -0.31 -0.20 -0.14 -0.19 -0.11 -0.35  0.31  1.00
## 
##  with tau of 
##             1     2    3
## c82cop1 -2.71 -1.22 0.73
## c83cop2 -0.82  0.89 1.71
## c84cop3  0.18  1.04 1.57
## c85cop4 -0.11  1.00 1.52
## c86cop5  0.51  1.46 2.13
## c87cop6  0.81  1.54 2.08
## c88cop7 -0.32  0.80 1.37
## c89cop8 -0.39  0.28 1.16
## c90cop9 -1.37 -0.46 0.41

La matriz de correlaciones policóricas es:

##            c82cop1    c83cop2    c84cop3     c85cop4    c86cop5      c87cop6
## c82cop1  1.0000000 -0.5045412 -0.3004853 -0.34908689 -0.2308785 -0.180465444
## c83cop2 -0.5045412  1.0000000  0.4739677  0.54947400  0.3608658  0.406264631
## c84cop3 -0.3004853  0.4739677  1.0000000  0.50321228  0.4709597  0.456616184
## c85cop4 -0.3490869  0.5494740  0.5032123  1.00000000  0.4133628  0.541998364
## c86cop5 -0.2308785  0.3608658  0.4709597  0.41336280  1.0000000  0.441997986
## c87cop6 -0.1804654  0.4062646  0.4566162  0.54199836  0.4419980  1.000000000
## c88cop7 -0.4604023  0.6234271  0.5763939  0.52145952  0.4330501  0.462032437
## c89cop8  0.1580285 -0.1372298 -0.1775943 -0.09963894 -0.1008317 -0.009949644
## c90cop9  0.3713749 -0.3101681 -0.1978129 -0.13974489 -0.1888892 -0.114126231
##            c88cop7      c89cop8    c90cop9
## c82cop1 -0.4604023  0.158028472  0.3713749
## c83cop2  0.6234271 -0.137229772 -0.3101681
## c84cop3  0.5763939 -0.177594307 -0.1978129
## c85cop4  0.5214595 -0.099638941 -0.1397449
## c86cop5  0.4330501 -0.100831683 -0.1888892
## c87cop6  0.4620324 -0.009949644 -0.1141262
## c88cop7  1.0000000 -0.168973130 -0.3489032
## c89cop8 -0.1689731  1.000000000  0.3108144
## c90cop9 -0.3489032  0.310814373  1.0000000

La matriz de umbrales o puntos de corte de cada ítem ordinal es:

##                  1          2         3
## c82cop1 -2.7134199 -1.2212917 0.7287596
## c83cop2 -0.8196479  0.8876615 1.7142953
## c84cop3  0.1816265  1.0426347 1.5748142
## c85cop4 -0.1118868  0.9975749 1.5173595
## c86cop5  0.5072586  1.4606039 2.1289376
## c87cop6  0.8141561  1.5363831 2.0772577
## c88cop7 -0.3230377  0.8025719 1.3686423
## c89cop8 -0.3923717  0.2804474 1.1646193
## c90cop9 -1.3684503 -0.4619124 0.4122173

19.0.7 Correlaciones: con hetcor()

La función hetcor() (del paquete polycor y significa heterogeneous correlations) necesita saber qué variables son numéricas continuas, ordinales y/o categóricas nominales. Por esta razón, si se convierten en factores, entonces:

  • Las variables ordinales serán tratadas como ordinales (si ya eran ordered).

  • Las variables nominales serán tratadas como categorical.

Cuando se ejecuta hetcor(), se obtiene un objeto de clase hetcor que incluye:

  1. correlations: Una matriz completa de correlaciones mixtas usando policórica, policerial, biserial, Pearson, según corresponda. Es ideal para análisis con variables mixtas (continuas + ordinales + nominales).

  2. std.errors (si se solicitan): Errores estándar de cada correlación estimada.

  3. call: El código original usado.

Así, esta función es extremadamente útil si tienes datos mixtos en un análisis preliminar, antes de correr un Modelo de Ecuaciones Estructurales.

library(polycor)  #Paquete Polycor: hetcor, polychor, poly.serial, print.polycor 
library(dplyr)

mydf %>%   mutate_all(.funs = list(as.factor)) %>%   hetcor() -> pc
pc
## 
## Two-Step Estimates
## 
## Correlations/Type of Correlation:
##         c82cop1    c83cop2    c84cop3    c85cop4    c86cop5    c87cop6
## c82cop1       1 Polychoric Polychoric Polychoric Polychoric Polychoric
## c83cop2 -0.5206          1 Polychoric Polychoric Polychoric Polychoric
## c84cop3 -0.2939     0.4664          1 Polychoric Polychoric Polychoric
## c85cop4 -0.3556     0.5538     0.5061          1 Polychoric Polychoric
## c86cop5 -0.2442     0.3619     0.4857     0.4137          1 Polychoric
## c87cop6 -0.1871     0.3955     0.4447     0.5321      0.447          1
## c88cop7  -0.449     0.6209     0.5712     0.5181     0.4394     0.4567
## c89cop8  0.1502    -0.1373    -0.1759    -0.0939     -0.101   -0.01539
## c90cop9  0.3737     -0.314    -0.2055    -0.1474    -0.1891     -0.126
##            c88cop7    c89cop8    c90cop9
## c82cop1 Polychoric Polychoric Polychoric
## c83cop2 Polychoric Polychoric Polychoric
## c84cop3 Polychoric Polychoric Polychoric
## c85cop4 Polychoric Polychoric Polychoric
## c86cop5 Polychoric Polychoric Polychoric
## c87cop6 Polychoric Polychoric Polychoric
## c88cop7          1 Polychoric Polychoric
## c89cop8    -0.1615          1 Polychoric
## c90cop9     -0.351     0.3197          1
## 
## Standard Errors:
##         c82cop1 c83cop2 c84cop3 c85cop4 c86cop5 c87cop6 c88cop7 c89cop8
## c82cop1                                                                
## c83cop2 0.03204                                                        
## c84cop3 0.04147 0.03465                                                
## c85cop4 0.03839  0.0296 0.03275                                        
## c86cop5 0.04656 0.04161 0.03714 0.03938                                
## c87cop6  0.0516 0.04447 0.04281 0.03759 0.04592                        
## c88cop7 0.03448 0.02597 0.02892 0.03048 0.03796 0.04065                
## c89cop8  0.0416 0.04021 0.04176 0.04075 0.04543 0.05092 0.03949        
## c90cop9 0.03625 0.03648 0.04086 0.04005 0.04392 0.04913 0.03494  0.0358
## 
## n = 881 
## 
## P-values for Tests of Bivariate Normality:
##          c82cop1   c83cop2   c84cop3   c85cop4   c86cop5 c87cop6   c88cop7
## c82cop1                                                                   
## c83cop2 0.002051                                                          
## c84cop3   0.1184    0.2257                                                
## c85cop4   0.4915    0.6549   0.01074                                      
## c86cop5   0.1206   0.03477  0.002069   0.00578                            
## c87cop6   0.7607    0.9429    0.7127    0.1981   0.01661                  
## c88cop7   0.1418 2.749e-05 0.0006003   0.06169 1.724e-05   0.254          
## c89cop8  0.02823 5.616e-05 0.0001083  0.002989    0.2531 0.00399  0.001295
## c90cop9  0.03763   0.09664 5.044e-05 0.0005481    0.1898  0.8933 0.0001217
##         c89cop8
## c82cop1        
## c83cop2        
## c84cop3        
## c85cop4        
## c86cop5        
## c87cop6        
## c88cop7        
## c89cop8        
## c90cop9 4.1e-06

La matriz de correlaciones se obtiene así:

pc$correlations
##            c82cop1    c83cop2    c84cop3     c85cop4    c86cop5     c87cop6
## c82cop1  1.0000000 -0.5205724 -0.2938970 -0.35558041 -0.2441937 -0.18708997
## c83cop2 -0.5205724  1.0000000  0.4663745  0.55381211  0.3618647  0.39554563
## c84cop3 -0.2938970  0.4663745  1.0000000  0.50613879  0.4857490  0.44466325
## c85cop4 -0.3555804  0.5538121  0.5061388  1.00000000  0.4136802  0.53211442
## c86cop5 -0.2441937  0.3618647  0.4857490  0.41368018  1.0000000  0.44702390
## c87cop6 -0.1870900  0.3955456  0.4446632  0.53211442  0.4470239  1.00000000
## c88cop7 -0.4489630  0.6208605  0.5711703  0.51814796  0.4394415  0.45674132
## c89cop8  0.1502221 -0.1373272 -0.1758758 -0.09389647 -0.1010439 -0.01539356
## c90cop9  0.3736961 -0.3140429 -0.2055051 -0.14742747 -0.1891189 -0.12601256
##            c88cop7     c89cop8    c90cop9
## c82cop1 -0.4489630  0.15022206  0.3736961
## c83cop2  0.6208605 -0.13732723 -0.3140429
## c84cop3  0.5711703 -0.17587581 -0.2055051
## c85cop4  0.5181480 -0.09389647 -0.1474275
## c86cop5  0.4394415 -0.10104389 -0.1891189
## c87cop6  0.4567413 -0.01539356 -0.1260126
## c88cop7  1.0000000 -0.16151531 -0.3510279
## c89cop8 -0.1615153  1.00000000  0.3197313
## c90cop9 -0.3510279  0.31973126  1.0000000

19.0.8 Correlaciones: advertencia importante

Si se tiene variables continuas reales, se sugiere no convertirlas en factor. La versión correcta sería con across():

mydf2 <- mydf %>%
  mutate(across(where(is.integer),    ~ factor(., ordered = TRUE))) %>% 
  mutate(across(where(is.character),  ~ factor(.))) %>% 
  mutate(across(where(is.numeric),    ~ .))

19.0.9 Heatmap de correlaciones: global

El paquete corrplot puede graficar cualquier matriz de correlaciones, independientemente del método con que haya sido calculada. En nuestro caso, trabajamos con dos matrices:

  • R_likert: matriz de correlaciones policóricas obtenida con polychoric(), adecuada cuando todas las variables son ordinales (ítems Likert).

  • pc$correlations: matriz de correlaciones heterogéneas (Pearson, polyserial y policórica combinadas) estimada con hetcor(), útil cuando hay variables de distinto tipo.

En ambos casos, corrplot() solo necesita una matriz numérica cuadrada. Por eso podemos usar indistintamente las dos formas siguientes:

# Primera forma: 
corrplot(
R_likert,
method  = "color",
tl.col  = "black",
tl.cex  = 0.7,
title   = "Correlaciones entre las variables COPE-Index",
mar     = c(0, 0, 2, 0)
)

#Segunda forma:
corrplot(
as.matrix(pc),
method  = "color",
tl.col  = "black",
tl.cex  = 0.7,
title   = "Correlaciones entre las variables COPE-Index",
mar     = c(0, 0, 2, 0)
)

Ambos comandos producen un heatmap válido, aunque la matriz de entrada provenga de algoritmos distintos. La primera opción refleja únicamente relaciones ordinales (correlaciones policóricas), mientras que la segunda combina el tipo de correlación más adecuado según el tipo de variable (continua u ordinal).

19.0.10 Heatmap de correlaciones: global y personalizada

En el siguiente ejemplo ajustamos varios argumentos de corrplot() para personalizar el mapa de calor: ordenamos las variables por agrupamiento, dibujamos rectángulos que marcan posibles “grupos” de ítems y modificamos colores, tamaños de texto y tratamiento de la significancia. Cada argumento está numerado y explicado en el propio código con comentarios.

corrplot(
  as.matrix(pc),              #1  Convertimos el objeto `pc` (hetcor) en matriz numérica
  method = "color",           #2  Representación en colores según magnitud de correlación
  addgrid.col = "darkgray",   #3  Color de la cuadrícula que separa cada celda
  order = "hclust",           #4  Ordenamiento basado en clustering jerárquico
  addrect = 3,                #5  Dibujar 3 rectángulos (3 clusters) alrededor de grupos similares
  rect.col = "black",         #6  Color del borde de esos rectángulos
  rect.lwd = 5,               #7  Grosor del borde de los rectángulos
  cl.pos = "b",               #8  Posición de la barra de color (“b” = bottom)
  tl.col = "indianred4",      #9  Color del texto (labels de variables)
  tl.cex = 0.6,               #10 Tamaño del texto de las etiquetas
  addCoef.col = "white",      #11 Color de los coeficientes escritos en las celdas
  number.digits = 1,          #12 Número de decimales de los coeficientes
  number.cex = 0.5,           #13 Tamaño del texto de los coeficientes
  tl.srt = 45,                #14 Rotación (45°) del texto de las etiquetas de variables
  title = "Three groups",     #15 Título del gráfico
  mar = c(0,0,1,0),           #16 Ajuste de márgenes para que el título se vea correctamente
  sig.level = 0.05,           #17 Nivel de significancia para filtrar correlaciones
  insig = "blank",            #18 No mostrar correlaciones no significativas
  col = colorRampPalette(     #19 Paleta personalizada para el gradiente de correlaciones
    c("darkred","white","midnightblue"))(100)
)

19.0.11 Heatmap por grupo (hombres vs mujeres)

Vamos a comparar las correlaciones entre:

  • Hombres (c161sex = 1).

  • Mujeres (c161sex = 2).

mydf_male <- datos %>% filter(c161sex == 1) %>% dplyr::select(matches("cop"))
mydf_female <- datos %>% filter(c161sex == 2) %>% dplyr::select(matches("cop"))

R_male <- polychoric(mydf_male)$rho
R_female <- polychoric(mydf_female)$rho

par(mfrow = c(1, 2))

corrplot(R_male,
method="color", tl.col="black", tl.cex=.6,
title="Correlaciones (Hombres)",
mar=c(0,0,2,0))

corrplot(R_female,
method="color", tl.col="black", tl.cex=.6,
title="Correlaciones (Mujeres)",
mar=c(0,0,2,0))

par(mfrow = c(1, 1))

20 Comentarios finales

  1. Para variables continuas aproximadamente normales, la matriz de covarianzas o correlaciones de Pearson suele ser suficiente.

  2. Para variables ordinales/dicotómicas, usar Pearson puede subestimar la correlación latente. En esos casos:

    • Dicotómicas: correlación tetracórica.

    • Ordinales con más de 2 categorías: correlación policórica.

  3. La función mixedCor() calcula automáticamente la correlación apropiada para cada par de variables, produciendo una matriz mixta muy útil para SEM.

  4. Con lavaan podemos usar esta información junto con un estimador robusto para variables categóricas (por ejemplo, WLSMV) y así ajustar modelos CFA/SEM coherentes con la naturaleza de los datos.

  5. Los heatmaps de correlación, tanto globales como por grupos, son una herramienta muy útil para la exploración inicial y para comunicar resultados de manera visual en clases, informes y artículos científicos.

21 Ejercicios

21.0.1 Ejercicios del 1 al 7

  1. Un local comercial ha determinado que el coeficiente de correlación entre sus gastos mensuales y sus ganancias hace dos años es \(r=0.56\). Suponga que tanto los gastos como las ganancias son aproximadamente normales y ponga a prueba la hipótesis nula \(H_0: \rho=0\) contra la hipótesis alternativa \(H_1: \rho\neq0\), con el nivel de significancia de 0.05.
  1. A partir de una muestra de 12 botellas de agua, un investigador encontró que el peso de la botella vacía y el contenido neto de la botella guardan una correlación de \(r=0.46\). Con base en esta muestra, deduzca diga si puede usarse el contenido neto de la botella para predecir su peso. Use \(\alpha=0.01\) y suponga que el contenido neto y el peso de las botellas siguen una distribución normal.
  1. Un comerciante determinó que la correlación entre las utilidades mensuales (millones de pesos) y los gastos mensuales (en millones en pesos) fue de \(r=0.61\) para un periodo de 1 año. Determine si hay una correlación positiva entre las utilidades y los gastos mensuales, asumiendo que estos dos siguen una distribución normal por mes. Use \(\alpha=0.01\).
  1. Utilizando una muestra de 30 pares de zapatos, un comerciante encontró que la correlación lineal entre el costo de un par y su peso neto (la suma de los pesos de los dos zapatos) es de \(r=0.81\). Si el costo del par de zapatos y su peso neto siguen una distribución normal, pruebe la hipótesis nula \(H_0: \rho \leq 0\) contra la hipótesis alternativa \(H_1: \rho>0\). Use \(\alpha=0.05\).
  1. En un estudio para determinar la relación entre la altura de un árbol de mango (1 año después de sembrar una semilla) y 3 años más tarde, una muestra de 20 registros dio como resultado \(r=0.57\). Haga una prueba para determinar si el coeficiente de correlación poblacional es positivo, suponiendo que la población de los pesos en cuestión sigue una distribución normal. Use \(\alpha=0.05\).
  1. El nivel de amebas y el consumo de agua sin hervir para una muestra de 25 personas dio un coeficiente de correlación \(r=0.78\). Determine si hay una correlación positiva entre el nivel de amebas y el consumo de agua sin hervir. Asuma que las poblaciones de valores en cuestión siguen una distribución normal. Use \(\alpha=0.05\).
  1. De una muestra de \(n=10000\) parejas \((x,y)\), se encontró que r=0.022. Pruebe \(H_0: \rho=0\) contra \(H_1:\rho \neq 0\) al nivel 0.05. ¿Es estadísticamente importante el resultado? Comente sobre el significado práctico de su análisis.

21.0.2 Ejercicio 8

Los siguientes datos representan el número \(x\) de proyectos presentados el año pasado por 12 universidades privadas y la ayuda recibida \(y\) (en millones de pesos) para la ejecución de estos proyectos:

x <- c(15.7, 17.2, 13.8, 24.2, 15.0, 12.7, 13.8, 18.7, 10.8, 11.8, 25.4, 17.2)

y <- c( 4 ,  3 ,  6 ,  5 ,  3 , 12 ,  5 ,  1 , 12 , 11 ,  2 ,  4 )
\(x\) 15.7 17.2 13.8 24.2 15 12.7 13.8 18.7 10.8 11.8 25.4 17.2
\(y\) 4.0 3.0 6.0 5.0 3 12.0 5.0 1.0 12.0 11.0 2.0 4.0
  1. Determine el coeficiente de correlación \(r\) de Pearson.

  2. Haga una prueba, con \(\alpha=0.05\), para determinar si el número de proyectos está relacionado con las ayudas recibidas.

  3. Pruebe la hipótesis nula \(H_0: \rho\leq 0\) contra la hipótesis alternativa \(H_1: \rho>0\), usando \(\alpha=0.05\).

  4. Calcule el coeficiente de determinación e interprete el resultado.

21.0.3 Ejercicio 9

Los siguientes datos representan los gastos anuales en publicidad \(x\) (en millones de pesos) y las ventas \(y\) (en millones de pesos):

x <- c(4.17, 10.04, 6.02, 1.52, 4.81, 7.70, 3.63, 4.65, 2.97, 1.57, 0.98, 1.57,
            6.09, 3.08, 1.76, 3.09, 4.18)

y <- c(96.97, 154.70, 151.61, 163.92, 147.82, 141.77, 179.18, 171.81, 200.23, 125.19, 120.49, 98.61,
            196.67, 289.59, 105.71, 275.97, 95.83)
\(x\) 4.17 10.04 6.02 1.52 4.81 7.70 3.63 4.65 2.97
\(y\) 96.97 154.70 151.61 163.92 147.82 141.77 179.18 171.81 200.23
\(x\) 1.57 0.98 1.57 6.09 3.08 1.76 3.09 4.18
\(y\) 125.19 120.49 98.61 196.67 289.59 105.71 275.97 95.83
  1. Halle el coeficiente de correlación muestral

  2. Contraste, frente a una alternativa bilateral, la hipótesis nula de que la correlación poblacional es 0.

21.0.4 Ejercicio 10

En una muestra aleatoria de 353 habitantes de cierto país, se halló que la correlación entre el ingreso mensual y los gastos en servicios públicos era 0.11.

  1. Halle el coeficiente de determinación de una regresión de los gastos en servicios públicos sobre el ingreso mensual para esa muestra. Interprete el resultado.

  2. Contraste la hipótesis nula de que estas cantidades no se hallan correlacionadas en la población, frente a la alternativa de que la correlación poblacional es positiva.

21.0.5 Ejercicio 11

Los siguientes datos representan los gastos (en miles de pesos) en los servicios de agua (\(x\)) y luz (\(y\)), durante un determinado mes, de seis familias seleccionadas al azar:

x <-  c(80, 74, 65, 83, 70, 92, 75, 88, 95, 60, 72, 78, 85, 90, 67, 81)

y <- c(63, 87, 78, 90, 74, 84, 70, 88, 92, 65, 73, 80, 89, 91, 72, 85)
\(x\) 80 74 65 83 70 92 75 88 95 60 72 78 85 90 67 81
\(y\) 63 87 78 90 74 84 70 88 92 65 73 80 89 91 72 85
  1. Calcule e interprete el coeficiente de correlación de \(x\) y \(y\).

  2. Pruebe la hipótesis de que \(\rho=0\) contra la alternativa de que \(\rho \neq 0\). Utilice un nivel de significancia de 0.05.

21.0.6 Ejercicio 12

Los siguientes datos se obtienen en un estudio de la relación entre el peso \(x\) (en kilogramos) y el volumen \(y\) (en centímetros cúbicos) de un tipo de recipiente:

x <- c(5.52, 3.21, 4.32, 2.31, 4.30, 3.71, 2.75, 2.15, 4.41)

y <-  c(36.5, 27.2, 27.7, 28.3, 30.3, 29.7, 29.5, 26.3, 32.2)
\(x\) 5.52 3.21 4.32 2.31 4.3 3.71 2.75 2.15 4.41
\(y\) 36.50 27.20 27.70 28.30 30.3 29.70 29.50 26.30 32.20
  1. Calcule el coeficiente de correlación muestral \(r\).

  2. Pruebe la hipótesis nula \(\rho=0\) contra la alternativa \(\rho>0\), con un nivel de significancia de 0.01.

  3. ¿Qué porcentaje de la variación en los volúmenes de los recipientes se explica por la diferencia en peso?

21.0.7 Ejercicio 13

Se recolectó una muestra de \(n=500\) parejas \((x,y)\) y se realizó una prueba de \(H_0:\rho=0\) contra \(H_1: \rho \neq 0\). El \(P\)-valor resultante es 0.00032.

  1. ¿Cuál conclusión sería apropiada al nivel de significancia 0.001?

  2. ¿Indica este pequeño \(P\)-valor que hay una relación lineal muy fuerte entre \(x\) y \(y\) (un valor de \(\rho\) que difiere considerablemente de 0)? Explique.

21.0.8 Ejercicio 14

Se ha seleccionado una muestra aleatoria de 12 estudiantes de bachillerato que han repetido el séptimo grado este año y, para cada uno, se ha anotado el promedio global de las calificaciones de todas las asignaturas, tanto el de este año (\(y\)) como el del año pasado (\(x\)), así:

x <- c(65, 55, 70, 65, 70, 55, 70, 50, 55, 65, 50, 55)

y <- c(90, 85, 87, 94, 98, 81, 91, 76, 74, 85, 74, 76)
\(x\) 65 55 70 65 70 55 70 50 55 65 50 55
\(y\) 90 85 87 94 98 81 91 76 74 85 74 76
  1. Calcule e interprete el coeficiente de correlación muestral.

  2. Establezca las suposiciones necesarias sobre las variables aleatorias.

  3. Pruebe la hipótesis de que \(\rho=0.5\) contra la alternativa de que \(\rho > 0.5\). Utilice un \(P\)-valor en las conclusiones.

21.0.9 Ejercicio 15

Los siguientes datos representan el volumen de lluvia \(x\) (en m\(^3\)) y el volumen de escurrimiento \(y\) (en m\(^3\)) para determinado lugar:

x <- c(23, 30, 40, 47, 5, 12, 14, 17, 55, 67, 72, 81, 96, 112, 127)

y <- c(15, 25, 27, 46, 4, 10, 13, 15, 38, 46, 53, 70, 82, 99, 100)
\(x\) 23 30 40 47 5 12 14 17 55 67 72 81 96 112 127
\(y\) 15 25 27 46 4 10 13 15 38 46 53 70 82 99 100
  1. ¿Respalda el diagrama de dispersión de los datos el uso del modelo de regresión lineal simple?

  2. Calcule los estimados puntuales de la pendiente y la ordenada al origen de la recta de regresión poblacional.

  3. Calcule un estimado puntual del volumen real de escurrimiento cuando el volumen de lluvia es 50.

  4. Calcule un estimado puntual de la desviación estándar \(\sigma\).

  5. ¿Qué porporción de la variación observada de volumen de escurrimiento se puede atribuir a la relación de regresión simple entre escurrimiento y lluvia?

21.0.10 Ejercicio 16

Los siguientes datos representan el tiempo de vida \(x\) de un bombillo de marca A (en horas), así como el tiempo de vida \(y\) de un bombillo de marca B (en minutos):

x <- c(4200, 3600, 3750, 3675, 4050, 2770, 4870, 4500, 3450, 2700, 3750, 3300)

y <- c(370, 340, 375, 310, 350, 200, 400, 375, 285, 225, 345, 285)
\(x\) 4200 3600 3750 3675 4050 2770 4870 4500 3450 2700 3750 3300
\(y\) 370 340 375 310 350 200 400 375 285 225 345 285
  1. Calcule e interprete el valor del coeficiente de correlación muestral \(r\).

  2. ¿Cómo cambiaría el valor de \(r\) si \(x\) es el tiempo del bombillo de marca B y \(y\), del bombillo de marca A?

  3. ¿Cómo cambiaría el valor de \(r\) si el tiempo \(y\) se expresara en horas?

  4. Trace gráficas de probabilidad normal y coméntelas.

  5. Realice una prueba de hipótesis para decidir si el tiempo \(x\) y el tiempo \(y\) están correlacionados linealmente.

21.0.11 Ejercicio 17

Un artículo mostró los siguientes datos sobre el tiempo de falla \(y\) (en segundos) de un componente electrónico y la temperatura \(x\) donde se emplea el componente (en grados centígrados):

x <- c(57, 60, 72, 81, 85, 94, 46, 48, 109, 121, 132, 137, 148, 149, 184, 185, 187, 55)

y <- c(2.28, 2.34, 2.53, 2.28, 2.62, 2.63, 2.18, 2.10, 2.50, 2.66, 2.79, 2.80, 3.01, 
       2.98, 3.34, 3.49, 3.26, 2.13)
\(x\) 57.00 60.00 72.00 81.00 85.00 94.00 46.00 48.0 109.0
\(y\) 2.28 2.34 2.53 2.28 2.62 2.63 2.18 2.1 2.5
\(x\) 121.00 132.00 137.0 148.00 149.00 184.00 185.00 187.00 55.00
\(y\) 2.66 2.79 2.8 3.01 2.98 3.34 3.49 3.26 2.13
  1. Calcule el valor del coeficiente de correlación muestral. Con base en este valor, ¿cómo describiría la naturaleza de la relación entre las dos variables?

  2. Si un primer componente tiene mayor valor de temperatura que un segundo componente, ¿qué se puede decir acerca del tiempo de falla real para los dos componentes?

  3. Si el tiempo de falla se expresa en minutos, ¿qué sucede con el valor \(r\)? ¿Por qué?

  4. Si el modelo de regresión lineal simple se ajustara a estos datos, ¿qué proporción de la variación observada de tiempo de falla se podría explicar con la relación del modelo?

  5. Realice una prueba, con nivel de significancia de 0.01, para decidir si hay una relación lineal positiva entre las dos variables.

21.0.12 Ejercicio 18

Un estudio reporta datos sobre la edad \(x\) de un paciente y el cambio \(y\) en el nivel de azúcar en la sangre por efecto de una droga. Los estadísticos de resumen son:

\[n=26, \quad \sum x_i=1613, \quad \sum (x_i-\overline{x})^2=3756.96, \quad \sum y_i=281.9, \quad \sum (y_i-\overline{y})^2=465.34, \quad \sum x_iy_i=16731\]

  1. Calcule un intervalo de confianza de 90% para el verdadero coeficiente de correlación \(\rho\).

  2. Pruebe \(H_0:\rho=-0.5\) contra \(H_1:\rho<-0.5\) en nivel 0.05.

  3. En un análisis de regresión de \(y\) en \(x\), ¿qué proporción de variación en el cambio del nivel de azúcar en la sangre podría ser explicada por la variación en edad del paciente dentro de la muestra?

  4. Si decide realizar un análisis de regresión, con la edad como variable dependiente, ¿qué proporción de variación en edad se explica por la variación en el nivel de azúcar en la sangre?

21.0.13 Ejercicio 19

En un estudio se presentan los siguientes datos sobre el promedio \(y\) de nivel de plomo en la sangre de los trabajadores de cierta empresa y la cantidad \(x\) de plomo utilizado en la producción de gasolina (en miles de toneladas), durante diez periodos de seis meses:

x <- c(80, 95, 95, 97, 102, 102, 107, 48, 59, 79)

y <- c(14.1, 13.6, 13.8, 14.6, 14.6, 16.0, 18.2, 9.3, 11.0, 12.8)
\(x\) 80.0 95.0 95.0 97.0 102.0 102 107.0 48.0 59 79.0
\(y\) 14.1 13.6 13.8 14.6 14.6 16 18.2 9.3 11 12.8
  1. Construya gráficas de probabilidad normal separadas para \(x\) y \(y\). ¿Es razonable suponer que los pares \((x,y)\) provienen de una población normal bivariada? Sugerencia: aplique el código de abajo e interprete.

  2. ¿Proporcionan los datos suficiente evidencia para concluir que hay una relación lineal entre el nivel de plomo en la sangre y la cantidad de plomo empleado en la producción de gasolina? Utilice \(\alpha =0.01\).
df <- data.frame(x, y)

par(mfrow = c(1, 2))

qqnorm(x,
       main = "Gráfica de probabilidad\n normal para x",
       pch = 19)
qqline(x, col = "red", lwd = 2)

qqnorm(y,
       main = "Gráfica de probabilidad\n normal para y",
       pch = 19)
qqline(y, col = "red", lwd = 2)

par(mfrow = c(1, 1))  # restaurar layout

Bibliografía

Consultar el documento RPubs :: Análisis multivariado (bibliografía).

 

 
If you found any ERRORS or have SUGGESTIONS, please report them to my email. Thanks.