Lección 3: Azar y recuento
Construye en Python el patrón «Tablero de Galton» y aprende por el camino:
- números aleatorios con np.random.default_rng
- True y False contados como 1 y 0
- contar con np.bincount
- una lista por comprensión
- una simulación comprobada con una fórmula
Míralo primero
Se reproduce desde YouTube tras hacer clic.
"""Galton board: every ball goes left or right at random at each of 12 rows of pegs.
Run: python galton-board.py (needs: pip install numpy matplotlib)
"""
from math import comb
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("dark_background")
rows, balls, p = 12, 5000, 0.5 # p: the chance of bouncing right
rng = np.random.default_rng()
bins = (rng.random((balls, rows)) < p).sum(axis=1) # a ball's bin = how often it went right
counts = np.bincount(bins, minlength=rows + 1)
k = np.arange(rows + 1)
expected = [balls * comb(rows, i) * p**i * (1 - p) ** (rows - i) for i in k] # the binomial curve
plt.figure(figsize=(7, 4))
plt.bar(k, counts, color="#5eead4", label="balls")
plt.xlabel("bin = times the ball went right")
plt.plot(k, expected, color="white", label="C(n, k) p^k (1-p)^(n-k)")
plt.legend()
plt.show()
# Try: p = 0.65 tilts the board; rows = 24 makes the bell narrower for its width
¿No tienes Python en este equipo? El cuaderno ejecuta el mismo script, los ejercicios y las respuestas en tu navegador, en Google Colab. El cuaderno está en inglés.
Línea a línea
rng = np.random.default_rng()El generador de números aleatorios de numpy. Dale un número, default_rng(1), y cada ejecución dará los mismos números «aleatorios».
bins = (rng.random((balls, rows)) < p).sum(axis=1)Una tabla de 5000 × 12 números aleatorios entre 0 y 1. Cada uno menor que p es True, un rebote a la derecha; al sumar una fila se cuentan sus True, y esa es la casilla de la bola.
counts = np.bincount(bins, minlength=rows + 1)Cuántas bolas cayeron en cada casilla, de la 0 a la 12; minlength se asegura de que las casillas vacías de los bordes cuenten como 0.
expected = [balls * comb(rows, i) * p**i * (1 - p) ** (rows - i) for i in k]Una lista por comprensión: la fórmula binomial para cada casilla i, multiplicada por el número de bolas.
plt.bar(k, counts, color="#5eead4", label="balls")Una barra por casilla. La línea blanca que se dibuja después es la fórmula, para comparar.
Pruébalo tú
Ejecuta el script dos veces. ¿Son iguales las barras? Después haz que todas las ejecuciones sean iguales.
Pista
Dale un número a default_rng.
Respuesta
Las barras cambian un poco cada vez. rng = np.random.default_rng(1) da la misma ejecución todas las veces.
¿Cuántas de 5000 bolas deberían caer en la casilla central con 12 filas?
Pista
La proporción de la casilla central es comb(12, 6) / 2**12.
Respuesta
5000 × 924 ÷ 4096 ≈ 1128.
Inclina el tablero con p = 0.65. ¿Dónde está ahora el centro de la campana?
Pista
El centro es rows · p.
Respuesta
12 × 0,65 = 7,8, así que el pico se desplaza a las casillas 7 y 8.
Cuestionario
Tarjetas de repaso
Lee el anverso, di el reverso para ti y luego abre la tarjeta.
np.random.default_rng(seed)
Un generador de números aleatorios; la misma semilla da los mismos números.
array < 0.5
Un array de True y False; True cuenta como 1 al sumar.
np.bincount(xs)
Cuántas veces aparece en xs cada número entero 0, 1, 2, …
[f(i) for i in k]
Una lista por comprensión: una lista nueva con f aplicada a cada elemento de k.
comb(n, k)
El número de maneras de elegir k cosas entre n: math.comb(12, 6) es 924.