Números Pseudoaleatorios · Tema 32

Correlación entre valores generados

Medir dependencias con código: Pearson por lags, correlograma con bandas y el AR(1) que enseña a leerlo.

01 · Punto de partida

Del veredicto a la medida

El Tema 28 preguntaba “¿pasa?” con bandas y Z. Este tema pregunta “¿cuánto?”: r(1) = 0,02 es ruido; r(1) = 0,6 es arrastre grave que invalida colas y varianzas simuladas. La correlación es el termómetro lineal de la dependencia: barata de calcular, fácil de graficar y honesta si se lee con sus límites.

El invitado didáctico es el AR(1): xₙ₊₁ = ρ·xₙ + ruido, cuya correlación decae ρʰ. Con él aprenderás a distinguir ruido, memoria corta y zigzag antes de tocar un generador real.

  • ¿Cómo se calcula r(h) paso a paso?
  • ¿Qué forma tiene un correlograma sano, uno AR(1) y uno alternado?
  • ¿Cuánto N hace falta para creerse un r = 0,05?
  • ¿Qué no ve Pearson aunque sea 0?

02 · Definición

Covarianza normalizada por lag

◈

Pearson r(h)

Covarianza entre uₙ y uₙ₊ₕ dividida la varianza: entre −1 y +1. Solo mide lo lineal.

⇄

Correlograma

Barras r(1)…r(10) con bandas ±1,96/√N: la firma visual de cada proceso. Sano = todas dentro.

▣

AR(1) ρ

xₙ₊₁ = ρ·xₙ + ε: r(h) = ρʰ. Con ρ = 0,6: 0,6 · 0,36 · 0,22… Memoria corta geométrica.

Firmas del correlograma.
Procesor(1)…r(3)Lectura
Sano≈ 0, 0, 0Sin arrastre lineal
AR(1) ρ = 0,60,6 · 0,36 · 0,22Memoria que decae ρʰ
Alternada−1 · +1 · −1Zigzag determinista

03 · Cálculo sin trampas

Dos pasadas, un N honesto

La forma estable: primera pasada para media y varianza, segunda para la covarianza por lag. Con N = 2000 la banda es ±0,044: un r(1) = 0,05 aislado no significa nada; r(1…5) ≈ 0,05 todos del mismo signo, sí.

N manda
El error típico de r es ≈ 1/√N: con N = 100 un r = 0,2 es ruido; con N = 10000 es condena. Informar r siempre con N y banda.
Lineal solamente
La parábola logística 4x(1−x) da r ≈ 0 y es determinista total. Pearson no ve curvas: para eso, series y scatter (Temas 30–31).
Rango Spearman (mención)
Si hay outliers o relación monótona no lineal, el Spearman por rangos es más robusto. Para uniformes sanos ambos ≈ 0; el curso usa Pearson por estándar.

Bien medido

r + banda + N

Correlograma 1…10, bandas por N, réplica con otra semilla. El número tiene contexto.

Mal medido

r solo

“r = 0,07, hay correlación” con N = 200 (banda ±0,14): ruido vendido como hallazgo.

04 · Ejemplos

Tres arrastres típicos

Secuencia→r(1…10)→Firma
  1. 1
    Sano, N = 2000.

    r(h) ≈ ±0,03 dentro de bandas: sin memoria lineal.

  2. 2
    AR(1) ρ = 0,6.

    Decaimiento 0,6 → 0,36 → 0,22: memoria corta honesta, útil como patrón de comparación.

  3. 3
    Alternada / juguete.

    −1/+1 fijos o corr positiva estable: dependencia estructural, no ruido.

05 · Implementación en Python

Correlograma con código

Función correlograma(us, hmax) en dos pasadas más un AR(1) didáctico para comparar firmas.

Python en tu navegador. Cambiá ρ a 0,9 y mirá cómo la memoria se alarga: r(5) aún ≈ 0,59.

import math
import random

def correlograma(us, hmax=5):
    n = len(us)
    m = sum(us) / n
    var = sum((u - m) ** 2 for u in us) / n
    out = []
    for h in range(1, hmax + 1):
        cov = sum((us[i] - m) * (us[i + h] - m) for i in range(n - h)) / (n - h)
        out.append(cov / var if var else 0.0)
    return [round(v, 4) for v in out]


rng = random.Random(32)
us = [rng.random() for _ in range(2000)]
print("sano:", correlograma(us))
print("banda:", round(1.96 / math.sqrt(2000), 4))

Cinco valores ≈ ±0,03 dentro de ±0,044: sin arrastre.

AR(1) con ρ = 0,6

import math
import random

def correlograma(us, hmax=5):
    n = len(us)
    m = sum(us) / n
    var = sum((u - m) ** 2 for u in us) / n
    return [round(sum((us[i] - m) * (us[i + h] - m) for i in range(n - h)) / (n - h) / var, 4)
            for h in range(1, hmax + 1)]


rng = random.Random(32)
x, rho, ruido = 0.0, 0.6, 0.8
ar = []
for _ in range(2000):
    x = rho * x + math.sqrt(max(1e-12, 1 - rho ** 2)) * (rng.random() - 0.5) * ruido
    ar.append(x)
print("AR(1):", correlograma(ar))

06 · Exploración

Laboratorio: firmas del arrastre

Cuatro fuentes con lags 1…8 y bandas del 95 %: sano (dentro), AR(1) ρ = 0,6 (decaimiento), alternada (−1/+1) y juguete (corr positiva). El panel trae r(1), máx |r| y lectura.

EXPERIMENTO 32

Cuánto arrastra

r(h) con bandas ±1,96/√N

Los resultados numéricos aparecen debajo.
r(1)—
Máx |r|—
Banda 95 %—
Lectura—

Sano con N = 800: arrastre ≈ 0.

Decaimiento geométrico = memoria corta; dientes −1/+1 = zigzag; barras positivas estables = ciclo.

Preguntas para explorar

  1. Con AR(1) y N = 2000: ¿r(1), r(2), r(3) siguen ρʰ = 0,6/0,36/0,22?
  2. Con sano y N = 200: ¿alguna barra sale? ¿Con N = 2000?
  3. Con juguete: ¿el signo de r(1) es estable al cambiar N? ¿Qué indica?
Ver respuestas sugeridas
  1. Sí, ±0,05: la firma teórica aparece con N grande. Con N = 200 el ruido la tapa.
  2. Con N = 200 (banda ±0,14) casi todo entra por falta de potencia; con N = 2000 el sano sigue dentro.
  3. Sí, positiva estable: dependencia estructural del ciclo, no azar.

07 · Comprensión

Confusiones frecuentes

«r = 0,07 con N = 200: hay correlación»

La banda es ±0,14: 0,07 es ruido. Sin N y banda, r es un número huérfano.

«r ≈ 0, el generador es independiente»

Solo sin dependencia lineal: la logística 4x(1−x) da r ≈ 0 determinista. Faltan series y scatter.

«Un lag alto con r grande es mejor memoria»

Al revés: en un generador r(h) debe ser ≈ 0 en todo h. Memoria ≠ calidad; memoria = defecto (salvo que simules un AR a propósito).

«Pearson o Spearman dan lo mismo»

En uniformes sanos sí; con outliers o monotonías no lineales difieren. Para auditoría estándar del curso: Pearson.

08 · Práctica guiada

Ejercicios con Python

Ejercicio 1: banda honesta

Con N = 800 de random, verificá que r(1…5) cae en ±1,96/√800 ≈ ±0,069.

import math
import random

def r1(us, h):
    n = len(us)
    m = sum(us) / n
    var = sum((u - m) ** 2 for u in us) / n
    cov = sum((us[i] - m) * (us[i + h] - m) for i in range(n - h)) / (n - h)
    return cov / var


rng = random.Random(7)
us = [rng.random() for _ in range(800)]
print([round(r1(us, h), 4) for h in range(1, 6)], "banda:", round(1.96 / math.sqrt(800), 4))
Ver solución razonada

Cinco valores dentro de ±0,069: pasa. Uno en 0,08 aislado se confirma con otra semilla.

Ejercicio 2: AR(1) a mano

Generá un AR(1) con ρ = 0,6 y comprobá r(1) ≈ 0,6 y r(3) ≈ 0,22.

import math
import random

rng = random.Random(7)
x, rho, n = 0.0, 0.6, 2000
ar = []
for _ in range(n):
    x = rho * x + math.sqrt(1 - rho ** 2) * (rng.random() - 0.5)
    ar.append(x)
m = sum(ar) / n
var = sum((v - m) ** 2 for v in ar) / n
for h in [1, 3]:
    cov = sum((ar[i] - m) * (ar[i + h] - m) for i in range(n - h)) / (n - h)
    print(h, round(cov / var, 4))
Ver solución

r(1) ≈ 0,58–0,62 y r(3) ≈ 0,20–0,24: la firma ρʰ con ruido muestral honesto.

Ejercicio 3: logística que engaña a Pearson

Mostrá que xₙ₊₁ = 4xₙ(1−xₙ) da r(1) ≈ 0 aunque es determinista.

Ver una posible respuesta
x = 0.3
us = []
for _ in range(2000):
    x = 4 * x * (1 - x)
    us.append(x)
m = sum(us) / len(us)
var = sum((u - m) ** 2 for u in us) / len(us)
cov = sum((us[i] - m) * (us[i + 1] - m) for i in range(len(us) - 1)) / (len(us) - 1)
print("r1:", round(cov / var, 4))

r(1) ≈ 0,0–0,1: Pearson “absuelve” un determinismo total no lineal. Por eso existen series y scatter.

09 · Síntesis

Ideas para recordar

  • r(h) = cov/var, entre −1 y +1; sano ≈ 0 ± 2/√N.
  • Firmas: sano plano, AR(1) decae ρʰ, alternada −1/+1.
  • r sin N y banda no dice nada; N chico todo lo perdona.
  • Pearson solo ve lo lineal: r ≈ 0 no certifica.
  • Memoria en un generador = defecto; en un modelo AR = diseño.

En el próximo tema veremos qué rompe todo: problemas de períodos cortos que arruinan simulaciones.