Listas y estructuras:

Extracción de bolas de una urna

Danna Cruz

Idea central de la clase

Hoy vamos a usar listas para representar objetos de un experimento aleatorio.

En lugar de pensar solo en números, pensaremos en una urna que contiene bolas de distintos colores.

Con Python podremos:

  • representar la urna como una lista,
  • extraer bolas al azar,
  • comparar qué ocurre con reemplazo y sin reemplazo,
  • y analizar cómo cambian las probabilidades cuando cambia la composición de la urna.

Recordemos: ¿qué es una lista?

Una lista es una estructura que permite guardar varios valores en un solo objeto.

Por ejemplo:

urna = ["roja", "azul", "verde", "roja", "azul"]
print(urna)

Salida:

['roja', 'azul', 'verde', 'roja', 'azul']

Aquí cada elemento de la lista representa una bola dentro de la urna.

¿Por qué usar listas en probabilidad?

Porque una lista nos permite representar de manera muy natural un experimento.

Si tenemos una urna con:

  • 3 bolas rojas,
  • 2 bolas azules,
  • 1 bola verde,

podemos escribir:

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]
print(urna)

Cada aparición en la lista cuenta como una bola real.

Primer experimento: extraer una bola

Para seleccionar un elemento al azar de una lista usamos random.choice().

import random

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]
bola = random.choice(urna)

print("Bola extraída:", bola)

Cada vez que ejecutes el código puede salir un resultado distinto.

Interpretación probabilística

Si la urna es:

["roja", "roja", "roja", "azul", "azul", "verde"]

entonces hay:

  • 3 rojas de 6 bolas,
  • 2 azules de 6 bolas,
  • 1 verde de 6 bolas.

Por tanto,

\[ P(\text{roja}) = \frac{3}{6} \]

\[ P(\text{azul}) = \frac{2}{6} \]

\[ P(\text{verde}) = \frac{1}{6} \]

La simulación nos ayuda a aproximar estas probabilidades.

Simular muchas extracciones

Si repetimos el experimento muchas veces, podemos contar cuántas veces aparece cada color.

import random

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]

rojas = 0
azules = 0
verdes = 0

for i in range(1000):
    bola = random.choice(urna)
    
    if bola == "roja":
        rojas += 1
    elif bola == "azul":
        azules += 1
    else:
        verdes += 1

print("Rojas:", rojas)
print("Azules:", azules)
print("Verdes:", verdes)

Frecuencia relativa

Para aproximar probabilidades, dividimos entre el número total de extracciones.

import random

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]

rojas = 0
azules = 0
verdes = 0
n = 1000

for i in range(n):
    bola = random.choice(urna)
    
    if bola == "roja":
        rojas += 1
    elif bola == "azul":
        azules += 1
    else:
        verdes += 1

print("Frecuencia de roja:", rojas / n)
print("Frecuencia de azul:", azules / n)
print("Frecuencia de verde:", verdes / n)

A medida que n crece, estas frecuencias suelen acercarse a las probabilidades teóricas.

Extracción con reemplazo

Con reemplazo significa que, después de sacar una bola, la devolvemos a la urna.

Eso implica que la composición de la urna no cambia.

Por ejemplo, si saco una roja y la regreso, la urna sigue siendo la misma.

Entonces, en cada extracción:

  • el número de bolas no cambia,
  • las probabilidades tampoco cambian.

Simular dos extracciones con reemplazo

import random

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]

bola1 = random.choice(urna)
bola2 = random.choice(urna)

print("Primera bola:", bola1)
print("Segunda bola:", bola2)

Aquí puede salir dos veces la misma bola en color, porque después de la primera extracción la urna sigue igual.

Extracción sin reemplazo

Sin reemplazo significa que la bola que sale ya no vuelve a la urna.

Entonces la composición sí cambia.

Eso tiene una consecuencia importante:

  • la probabilidad de la segunda extracción depende de lo que ocurrió en la primera.

Este detalle hace que el experimento sea distinto al caso con reemplazo.

Simular dos extracciones sin reemplazo

import random

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]

bola1 = random.choice(urna)
urna.remove(bola1)
bola2 = random.choice(urna)

print("Primera bola:", bola1)
print("Segunda bola:", bola2)

Observa que usamos remove() para sacar de la lista la bola obtenida.

Comparación conceptual

Supongamos una urna con:

["roja", "roja", "azul"]

Con reemplazo

Si la primera fue roja y la devolvemos, la segunda extracción sigue teniendo:

\[ P(\text{roja}) = \frac{2}{3} \]

Sin reemplazo

Si la primera fue roja y no la devolvemos, queda:

["roja", "azul"]

Entonces ahora:

\[ P(\text{roja}) = \frac{1}{2} \]

La probabilidad cambió.

Ejemplo guiado

Urna inicial:

urna = ["roja", "roja", "azul", "verde"]

Pregunta: ¿qué pasa con la probabilidad de sacar roja en la segunda extracción?

  • Con reemplazo: sigue siendo igual que al inicio.
  • Sin reemplazo: depende de la primera bola que salió.

Ese es el punto clave de la clase.

Usar listas para cambiar proporciones

Podemos modificar la urna fácilmente.

Por ejemplo:

urna1 = ["roja", "roja", "azul", "verde"]
urna2 = ["roja", "roja", "roja", "roja", "azul", "verde"]

En urna2 hay más bolas rojas, así que esperaríamos que aparezcan más veces al simular.

Comparar dos urnas

import random

urna1 = ["roja", "roja", "azul", "verde"]
urna2 = ["roja", "roja", "roja", "roja", "azul", "verde"]

rojas1 = 0
rojas2 = 0
n = 1000

for i in range(n):
    if random.choice(urna1) == "roja":
        rojas1 += 1
        
    if random.choice(urna2) == "roja":
        rojas2 += 1

print("Frecuencia de roja en urna1:", rojas1 / n)
print("Frecuencia de roja en urna2:", rojas2 / n)

¿Qué estamos aprendiendo realmente?

No solo estamos programando.

Estamos entendiendo que:

  1. una lista puede representar un espacio experimental simple,
  2. la simulación permite observar patrones,
  3. las probabilidades dependen de la composición de la urna,
  4. y el reemplazo cambia la lógica del experimento.

Error común 1

Confundir color con posición.

En una lista, varias bolas pueden tener el mismo color:

urna = ["roja", "roja", "roja", "azul"]

Aunque aparezca la palabra "roja" tres veces, cada una representa una bola distinta.

Error común 2

Modificar la urna original sin darse cuenta.

Mira este ejemplo:

urna = ["roja", "roja", "azul"]
urna.remove("roja")
print(urna)

Salida:

['roja', 'azul']

La lista cambió. Si necesitas conservar la original, puedes hacer una copia:

urna_copia = urna.copy()

Error común 3

Pensar que una simulación pequeña siempre refleja la probabilidad exacta.

Por ejemplo, si haces solo 10 extracciones, puede haber variación grande.

Pero si haces 1000 o 10000, normalmente los resultados se estabilizan más.

Actividad en clase

Trabajemos con esta urna:

urna = ["roja", "roja", "roja", "azul", "azul", "verde"]
  1. Simula una extracción.
  2. Simula dos extracciones con reemplazo.
  3. Simula dos extracciones sin reemplazo.
  4. Repite muchas veces y estima la probabilidad de sacar una bola azul.
  5. Cambia la urna para que tenga más bolas verdes y observa qué pasa.

Ejemplo completo: comparación con y sin reemplazo

import random

urna_original = ["roja", "roja", "roja", "azul", "azul", "verde"]
n = 1000

mismo_color_con = 0
mismo_color_sin = 0

for i in range(n):
    # Con reemplazo
    bola1 = random.choice(urna_original)
    bola2 = random.choice(urna_original)
    if bola1 == bola2:
        mismo_color_con += 1

    # Sin reemplazo
    urna = urna_original.copy()
    bola1 = random.choice(urna)
    urna.remove(bola1)
    bola2 = random.choice(urna)
    if bola1 == bola2:
        mismo_color_sin += 1

print("Prob. aproximada de mismo color con reemplazo:", mismo_color_con / n)
print("Prob. aproximada de mismo color sin reemplazo:", mismo_color_sin / n)

Reflexión

La simulación no reemplaza al cálculo teórico, pero sí ayuda a:

  • entender mejor el experimento,
  • visualizar cómo cambia una probabilidad,
  • y desarrollar intuición antes de formalizar.