01 · Punto de partida
Elegir m distintos de n
¿5 ganadores entre 20 inscriptos? ¿4 piezas a auditar de un lote de 50? ¿El 30 % de test sin filtrar nada al train? Cada elemento puede salir a lo sumo una vez: el resultado es un subconjunto de tamaño m, equiprobable entre los C(n,m).
Es el espejo del Tema 30: allí repetir era la información; aquí repetir es el bug. El motor pasa de índices iid a permutación parcial.
- ¿Por qué sortear índices iid y descartar repetidos sesga si se hace mal?
- ¿Qué probabilidad tiene cada elemento de salir?
- ¿Fisher-Yates parcial, Floyd o
samplesegún n y m? - ¿Cómo se audita con la hipergeométrica?
02 · Definición
Uniformidad sobre subconjuntos
P(S) = 1/C(n,m) para todo S de tamaño m. P(i ∈ S) = m/n por simetría. Si la población tiene K marcados, los marcados en la muestra son Hipergeométrica(n,K,m): media m·K/n.
Distintos garantizados
El algoritmo debe impedir el repetido por construcción (permutar, no reintentar): el rechazo ingenuo cambia el costo y, mal cortado, la ley.
Conteos hipergeométricos
Sin reemplazo los ensayos no son independientes: la varianza lleva el factor (n−m)/(n−1). Con m = n todo sale siempre.
Parcial vs total
Si m ≪ n, permutar todo desperdicia O(n): basta mezclar las primeras m posiciones o construir el conjunto directo.
| Hecho | Valor | Lectura |
|---|---|---|
| P(7 sale) | 5/20 = 0,25 | Cada elemento, 1 de cada 4 muestras |
| Subconjuntos | C(20,5) = 15 504 | Todos equiprobables |
| Defectuosas (K=4) | media 1,0 | m·K/n = 5·4/20 |
03 · Anatomía
Parcial, Floyd y descarte
- Fisher-Yates parcial O(m)
- Mezclar solo las primeras m posiciones: en el paso i sortear j ∈ {i,…,n−1} e intercambiar. Toma los primeros m: subconjunto uniforme sin tocar el resto.
- Floyd O(m) ordenado
- Construir el conjunto de atrás hacia adelante con inclusiones calibradas. Ideal con n enorme y m chico; devuelve ordenado, no en orden aleatorio.
- Rechazo con conjunto
- Sortear
int(n·U)y guardar si es nuevo hasta juntar m. Simple con m ≪ n; con m ≈ n las colisiones lo vuelven O(n log n) o peor. - Mezcla total + corte O(n)
- Permutar todo (Tema 33) y quedarse con los primeros m. La vía simple si n es chico o si además se necesita el orden aleatorio completo.
Parcial / Floyd
Eficientes con m ≪ n
Trabajo proporcional a la muestra, no a la población. La opción cuando n es catálogo y m es puñado.
Reintento sin control
Lento y frágil
Con m ≈ n casi todo sorteo colisiona; y si se “completa” con los que faltan, el subconjunto deja de ser uniforme.
04 · Dónde no se repite
Del sorteo al reparto
- 1Sorteos y loterías.
Ganadores, jurados, auditorías: nadie sale dos veces.
- 2Train / test.
Partir datos sin fuga: cada fila va a entrenar o a test, nunca a ambos.
- 3Control de calidad.
Piezas a inspeccionar de un lote: conteos hipergeométricos con K defectuosas.
- 4Puente a permutaciones.
El m = n es la permutación completa del Tema 32; Fisher-Yates total es el caso límite.
05 · Representación en Python
Parcial a mano contra sample
Misma población, mismo m: Fisher-Yates parcial manual frente a random.sample. Ambas deben dar inclusión ≈ m/n por elemento.
Python en tu navegador. Subí m a 15: la inclusión debe ir a 0,75.
import random
random.seed(270)
n, m, B = 20, 5, 4000
def subconjunto(m, n):
idx = list(range(n))
for i in range(m):
j = i + int((n - i) * random.random())
idx[i], idx[j] = idx[j], idx[i]
return sorted(idx[:m])
frec = [0] * n
for _ in range(B):
for i in subconjunto(m, n):
frec[i] += 1
print("parcial:", [round(f/B, 3) for f in frec[:5]], "vs", m/n)
random.seed(270)
frec2 = [0] * n
for _ in range(B):
for i in sorted(random.sample(range(n), m)):
frec2[i] += 1
print("sample: ", [round(f/B, 3) for f in frec2[:5]], "vs", m/n)
Inclusión ≈ 0,25 en ambas. Si algún índice da ≈ 0, el rango del sorteo parcial está mal.
06 · Exploración
Laboratorio: planicie de inclusión
Movete m y B con n = 20 fijo. Las barras son la frecuencia de inclusión de cada elemento 0…19; la línea es m/n. Con B grande, planicie; con B chica, ruido.
Subconjunto de m en 20
P(i ∈ S) = m/n
Con m 5 y B 2000, planicie en 0,25.
20 barras vs línea teórica. Probá m = 15 (línea 0,75) y B = 200 (ruido).
Preguntas para explorar
- Con m = 5, ¿inclusión teórica? ¿Chi-cuadrado chico?
- Subí m a 19. ¿Todas las barras van a ≈ 0,95? ¿Por qué?
- Bajá B a 200. ¿El error máx. crece? ¿Sesgo o ruido?
Ver respuestas sugeridas
- 0,25 y chi ≈ grados de libertad (19): el ruido esperado, no sesgo.
- Sí: cada muestra deja afuera solo 1 de 20, así que casi todos entran casi siempre.
- Ruido: el error típico por barra es √[p(1−p)/B] ≈ 0,01 con B = 2000 y ≈ 0,03 con B = 200.
07 · Comprensión
Confusiones frecuentes
«Sorteo m índices iid y listo»
Con reemplazo salen repetidos: ya no es subconjunto de tamaño m sino multiconjunto. Sin reemplazo exige construcción sin repetir.
«El rango del paso i da igual»
Debe ser {i,…,n−1}. Sortear en {0,…,n−1} en cada paso es el “Fisher-Yates ingenuo” sesgado del Tema 33.
«Ordeno el resultado y se arruina»
Ordenar el subconjunto no cambia la ley del conjunto; solo pierde el orden aleatorio (que Floyd ni siquiera produce).
«Con B = 100 ya valido»
La inclusión p = 0,25 con B = 100 tiene error típico ≈ 0,043 por barra: el chi baila. Validar con miles.
08 · Práctica guiada
Ejercicios con Python
Ejercicio 1: lote con defectuosas
Lote n = 20 con K = 4 defectuosas, m = 5, B = 6000 (semilla 271): la media de defectuosas debe dar ≈ 1,0.
import random
random.seed(271)
n, K, m, B = 20, 4, 5, 6000
malas = set(range(K))
tot = 0
for _ in range(B):
s = random.sample(range(n), m)
tot += sum(1 for i in s if i in malas)
print(round(tot/B, 3), "vs", m*K/n)
Ver solución razonada
≈ 1,0 (típicamente 0,95–1,05). Es la media hipergeométrica m·K/n sin reemplazo.
Ejercicio 2: P(0 defectuosas)
Mismo lote: estimá P(ninguna defectuosa) ≈ C(16,5)/C(20,5) ≈ 0,282.
import random
import math
random.seed(272)
n, K, m, B = 20, 4, 5, 6000
malas = set(range(K))
cero = sum(1 for _ in range(B)
if not any(i in malas for i in random.sample(range(n), m)))
print(round(cero/B, 3), "vs", round(math.comb(16,5)/math.comb(20,5), 3))
Ver solución
≈ 0,28. Con reemplazo daría (0,8)⁵ ≈ 0,328: el sin reemplazo “ayuda” a encontrar defectuosas.
Ejercicio 3: split train/test 70/30
Con n = 100, separá 70/30 con semilla fija y verificá disjuntos, unión completa y tamaños exactos.
Ver una posible respuesta
import random
random.seed(273)
n, m = 100, 70
train = set(random.sample(range(n), m))
test = set(range(n)) - train
print(len(train), len(test), len(train & test), len(train | test))
70, 30, 0 y 100: partición exacta sin fuga. Con reemplazo habría repetidos y huecos.
09 · Síntesis
Ideas para recordar
- Sin reemplazo: P(S) = 1/C(n,m), P(i ∈ S) = m/n.
- Conteos de clase ⇒ hipergeométrica, no binomial.
- Parcial O(m) o Floyd con m ≪ n; total + corte con n chico.
- Rango {i,…,n−1} en cada paso: el ingenuo sesga.
- Auditar inclusión por elemento + chi contra m/n.
En el próximo tema mezclamos todo: permutaciones aleatorias.