Misión 6. Mide sin engañarte
▶ Abrir en Colab ▶ Ejecutar en Binder
Colab abre en segundos. Binder, la primera vez, construye el entorno en la nube (10-20 min) y luego queda en caché.
Misión 6. Encargo: «¿de verdad el reggaeton es más bailable que el resto?».
Victoria: una comparación honesta, con su margen.
Insignia en juego: juez del dato.
El encargo
«El reggaeton es lo más bailable que hay.» Lo has oído mil veces: en el patio, en las fiestas, en cualquier discusión sobre música. Suena a verdad. Pero un analista no repite lo que suena a verdad —lo mide—. Y ahí empieza el problema de esta misión, que es más resbaladizo de lo que parece: en cuanto pones dos números uno al lado del otro, casi nunca son iguales. Cómo de bailable es el reggaeton saldrá distinto del pop; el pop, distinto del rock; el rock, distinto del funk. Siempre hay una diferencia. La pregunta de verdad no es «¿son distintos?» —lo son casi por definición—, sino otra mucho más incómoda: ¿esa diferencia significa algo, o es puro azar?
Aquí es donde muchísima gente se engaña, y no por tonta: por tener prisa. Ven que el reggaeton marca 0,77 y una sinfonía marca 0,32, gritan «¡lo sabía!» y a otra cosa. Otras veces ven que el reggaeton marca 0,772 y el dancehall 0,774, y también gritan «¡el dancehall gana!» —y esa segunda vez se equivocan de medio a medio, porque esas dos milésimas caben enteras dentro del temblor normal de los datos—. El oficio de esta misión es aprender a distinguir esos dos casos sin trampas. A eso lo vamos a llamar medir sin engañarte, y cuando lo domines te habrás ganado la insignia más seria de toda la campaña: juez del dato. Un juez no decide por corazonadas; escucha las pruebas, mide la duda que queda y solo entonces dicta sentencia —y si la prueba no llega, tiene el valor de decir «no se puede decidir»—.
El encargo concreto.
Spotify escucha cada canción y le pone, entre otras cosas, una danceability de 0 a 1: cuanto más alta, más te pide el cuerpo moverte. Tu encargo es responder, con el catálogo real que ya trajiste en misiones anteriores, a una pregunta que parece de respuesta obvia y no lo es tanto: ¿de verdad el reggaeton es más bailable que el resto?. Y no vale contestar «sí» a secas. Un juez del dato contesta con las tres cosas que hacen honesta una respuesta: cuánto más, con qué margen de duda, y por tanto si la diferencia es de fiar o podría ser casualidad. «El reggaeton es más bailable por 0,19 puntos, con un margen de menos de 0,04» es una respuesta de juez. «El reggaeton es más bailable» a secas es una opinión. (Y ojo a una trampa que ya asoma: «más bailable que el resto» y «el más bailable de todos» no son la misma frase. Ya llegaremos a ella.)
El mapa de la misión.
Vamos a construir esa respuesta pieza a pieza, y cada pieza es una micro-victoria —un número, una comparación, una figura— que puedes enseñar:
Resumir muchos datos en un solo número honrado: la media y su prima lista, la mediana.
Ver que el centro no basta: medir cuánto se dispersan los datos.
Descubrir, con un experimento, que una diferencia puede ser puro azar.
Ponerle a cada número su margen: «no me fío del último dígito».
Comparar dos grupos con honestidad, mirando si sus márgenes se pisan.
Juntarlo todo en un veredicto sobre el reggaeton —con su margen— y superar al jefe de parte.
Una advertencia de las que se agradecen: esto no es un curso de estadística —de eso hay carreras enteras—. Es lo justo para que un analista no se engañe ni engañe a nadie. Sin fórmulas en el camino (las pocas que hay viven en las cajas «Para saber más», por si quieres asomarte). Solo intuición, código que puedes ejecutar y la honestidad por bandera. Vamos allá.
Por qué esta misión importa más de lo que parece.
Vas a oír cifras toda tu vida —en anuncios, en política, en discusiones de internet, en el instituto—, y casi todas te llegarán peladas, sin margen y sin contexto: «tal producto es un 30 % más eficaz», «los de tal grupo sacan mejores notas», «este grupo de música es el más bailable». La inmensa mayoría de quien las dice no está mintiendo a propósito: simplemente no ha aprendido a preguntarse si su diferencia aguanta un examen honesto. Tú vas a aprenderlo en estas páginas, y a partir de aquí verás el mundo con otros ojos —los de quien, ante cualquier número, sabe hacer las dos preguntas que lo desnudan: ¿con qué margen? ¿podría ser azar?—. No es solo una destreza de programador; es una vacuna contra que te engañen.
La herramienta
Un número para resumir una sesión entera
Ya fabricaste la media en la Misión 1: sumar todo y dividir entre cuántos hay. Entonces era un ejercicio; ahora es una herramienta con un trabajo serio —aplastar muchos números en uno solo que los represente—. Una sesión de un DJ son decenas de canciones; una lista de reproducción, cientos. Nadie las juzga una a una. La media las resume en una cifra: «¿cómo de bailable fue, en conjunto, esta sesión?».
sesion = [0.72, 0.75, 0.71, 0.78, 0.74, 0.20]
media = sum(sesion) / len(sesion)
print("Suma:", round(sum(sesion), 2), " Canciones:", len(sesion))
print("Danceability media:", round(media, 2))Suma: 3.9 Canciones: 6
Danceability media: 0.65
Seis canciones de una sesión, resumidas en un 0.65. Cómodo… pero mira esas seis con lupa antes de seguir: 0,72, 0,75, 0,71, 0,78, 0,74 y cero coma veinte. Cinco de ellas rondan el 0,7 (temazos que llenan la pista); la sexta se hunde en 0,20 (pongamos que una balada lentísima se coló entre tema y tema). Y la media dice 0,65, un número por el que no pasó casi ninguna canción de la sesión: casi todas estuvieron bastante por encima, y una, muy por debajo. La media es honrada, pero tiene una debilidad —y aprender a verla es tu primer paso hacia no engañarte—.
La media se deja engañar: la mediana
La media suma todo, así que un solo valor perdido tira de ella como un imán. Esa balada de 0,20 no es «una sesión un poco menos bailable»: es un valle raro, y sin embargo empuja el resumen de la sesión entera hacia abajo. Para no dejarte engañar por un valor perdido existe otra forma de encontrar el centro, más terca y más lista: la mediana. Su receta no suma nada; ordena los valores de menor a mayor y se queda con el del medio —el que parte la lista en dos mitades iguales—.
def mediana(valores):
orden = sorted(valores)
n = len(orden)
centro = n // 2
if n % 2 == 1: # impar: hay uno justo en medio
return orden[centro]
return (orden[centro - 1] + orden[centro]) / 2 # par: promedio de los dos
sesion = [0.72, 0.75, 0.71, 0.78, 0.74, 0.20]
print("Ordenados:", sorted(sesion))
print("Media: ", round(sum(sesion) / len(sesion), 2))
print("Mediana:", mediana(sesion))Ordenados: [0.2, 0.71, 0.72, 0.74, 0.75, 0.78]
Media: 0.65
Mediana: 0.73
Ahí está la diferencia, y es enorme: la media dice 0,65 y la mediana dice 0,73. ¿Cuál miente? Ninguna —cuentan cosas distintas—. La mediana es el valor de en medio: la mitad de las canciones quedaron por debajo de 0,73 y la mitad por encima. Esa balada de 0,20, para la mediana, es un valor más de la mitad de abajo: da igual que valga 0,20 o que valga 0,05, sigue siendo «una de las bajas», y el del medio no se mueve. Por eso la mediana resiste los valles y los picos. La media, en cambio, se los traga enteros. Cuando hay seis valores y la lista es par, la mediana promedia los dos del centro (0,72 y 0,74 \(\rightarrow\) 0,73); con lista impar, es directamente el del medio.
Como la media, la mediana ya viene hecha en las herramientas de un analista. La biblioteca numpy —la caja de cálculo con la que trabaja todo el mundo que hace ciencia de datos— trae las dos, y coinciden con las tuyas al dígito:
import numpy as np
sesion = [0.72, 0.75, 0.71, 0.78, 0.74, 0.20]
print("Media (numpy): ", round(np.mean(sesion), 2))
print("Mediana (numpy):", np.median(sesion))Media (numpy): 0.65
Mediana (numpy): 0.73
Igual que en la Misión 1 fabricaste la media a mano antes de usar el atajo, ahora ya sabes lo que np.median hace por dentro: ordenar y partir por la mitad. No es una caja negra; es tu propia receta, más rápida. A partir de aquí puedes tirar de np.mean y np.median con toda la confianza del mundo.
¿Media o mediana? Cuándo fiarte de cada una
No es que una sea buena y otra mala: cuentan historias distintas, y el analista elige según la pregunta. Una regla que casi nunca falla:
Si los datos son parejos, sin valores locos, media y mediana se parecen mucho, y da igual cuál uses. Que se parezcan es, de hecho, una buena señal: los datos se portan bien.
Si hay valores raros o una cola larga —unas pocas canciones disparadas, una balada colada, un dato mal medido—, la media se va con ellos y la mediana aguanta. Para el «¿cómo es una canción normal?», la mediana suele ser más justa.
Y cuando media y mediana se separan mucho, eso ya es información: te está avisando de que ahí dentro hay valores extremos. Mirar las dos juntas es como tomar dos fotos del mismo sitio desde ángulos distintos.
Esto no es teoría abstracta: la música real hace justo eso. Cógete todas las canciones de reggaeton del catálogo y compara su media con su mediana:
reggaeton = musica[musica["track_genre"] == "reggaeton"]["danceability"]
print("reggaeton -> media:", round(reggaeton.mean(), 3),
" mediana:", round(reggaeton.median(), 3))reggaeton -> media: 0.772 mediana: 0.795
La media (0,772) queda por debajo de la mediana (0,795). No es casualidad: son unas pocas canciones de reggaeton flojas de baile —esas más de escuchar que de bailar— tirando de la media hacia abajo, mientras la mediana —el valor de la canción típica— se queda tranquila arriba. Casi cualquier grupo de datos del mundo real tiene alguna cola así. Por eso saber leer las dos cifras te salva de titulares tramposos. (Este código usa el musica que cargaremos en un momento; guárdalo en la cabeza y volvemos a él.)
El centro no basta: la dispersión
Aquí va la trampa más peligrosa de todas, y cae en ella gente muy lista: creer que con el centro ya está todo dicho. No lo está, ni de lejos. Mira estas dos listas de reproducción, cada una con cinco canciones:
import numpy as np
lista_a = [0.68, 0.71, 0.69, 0.72, 0.70]
lista_b = [0.50, 0.90, 0.60, 0.80, 0.70]
print("Media A:", np.mean(lista_a), " Media B:", np.mean(lista_b))
print("Rango A:", round(max(lista_a) - min(lista_a), 2),
" Rango B:", round(max(lista_b) - min(lista_b), 2))
print("Desviacion A:", round(np.std(lista_a), 2))
print("Desviacion B:", round(np.std(lista_b), 2))Media A: 0.7 Media B: 0.7
Rango A: 0.04 Rango B: 0.4
Desviacion A: 0.01
Desviacion B: 0.14
La misma media exacta: las dos listas marcan 0,70. Si te quedaras ahí, dirías «bailan igual» —y estarías engañándote a lo grande—. La lista A es un remanso: todas sus canciones pegaditas entre 0,68 y 0,72, un baile constante. La lista B es una montaña rusa: canciones de 0,50 y canciones de 0,90, de estar sentado a saltar. Suenan completamente distintas, y la media, ella sola, te lo ocultaba. Para no caer, todo número que resume necesita un compañero que diga cuánto se dispersan los datos a su alrededor. Dos formas de medirlo:
El rango: la distancia entre el mayor y el menor (
max - min). Sencillísimo. El de A es 0,04; el de B, 0,40. Ya lo dice casi todo. Su pega: solo mira los dos extremos y se olvida del resto.La desviación típica: la distancia a la que suelen estar las canciones respecto de la media. Es la reina de la dispersión. La de A es 0,01 (todo apretado); la de B, 0,14 (todo desparramado). Cuanto más grande, más nervioso el dato.
La desviación típica suena a palabra de mayores, pero la idea es de guardería: «¿cómo de lejos, en promedio, cae cada canción de su media?». Vamos a calcularla a mano una vez —igual que hicimos con la media— para que no te sea un conjuro:
lista_b = [0.50, 0.90, 0.60, 0.80, 0.70]
media = sum(lista_b) / len(lista_b)
cuadrados = [round((x - media) ** 2, 4) for x in lista_b]
varianza = sum(cuadrados) / len(lista_b)
print("Distancias al cuadrado:", cuadrados)
print("Desviacion tipica:", round(varianza ** 0.5, 2))Distancias al cuadrado: [0.04, 0.04, 0.01, 0.01, 0.0]
Desviacion tipica: 0.14
La receta, paso a paso: a cada canción le restas la media (así sabes lo lejos que cae), lo elevas al cuadrado (para que las distancias por abajo no se cancelen con las de por arriba, y de paso castigar más a las muy lejanas), lo promedias todo —eso se llama varianza— y, al final, le haces la raíz cuadrada para volver a las unidades de siempre. Sale 0,14, clavado a lo que dio np.std. Reconoce el patrón: es el mismo bucle de sumar-y-dividir de la media, con un par de pasos más. No hay magia; hay una cuenta que ahora entiendes.
Grábate esta pareja, porque es media misión: un centro nunca viaja solo. La media sin la dispersión es como decir «esta lista tiene una danceability media de 0,7» sin avisar de si es un baile constante o un vaivén de baladas y temazos. Centro y dispersión, siempre juntos.
Partir en cuatro: los cuartiles
La mediana partía los datos en dos mitades. Si sigues cortando por ahí sale una forma más rica de describir la dispersión sin depender de la media para nada: los cuartiles, que parten los datos ordenados en cuatro montones iguales. El primer cuartil (lo llaman Q1) deja por debajo la cuarta parte más baja; el segundo es la propia mediana; el tercero (Q3), las tres cuartas partes. La orden np.percentile los saca de un tiro —un percentil es «el valor por debajo del cual queda tal porcentaje de los datos», así que Q1 es el percentil 25, la mediana el 50 y Q3 el 75—:
import numpy as np
q1, q2, q3 = np.percentile(reggaeton, [25, 50, 75])
print("Q1 (25%):", round(q1, 2))
print("Mediana (50%):", round(q2, 2))
print("Q3 (75%):", round(q3, 2))
print("Rango intercuartil:", round(q3 - q1, 2))Q1 (25%): 0.71
Mediana (50%): 0.8
Q3 (75%): 0.83
Rango intercuartil: 0.13
Lee la ficha del reggaeton de un vistazo: la cuarta parte de las canciones menos bailables quedó por debajo de 0,71 (Q1); la mitad, por debajo de 0,80 (la mediana); y solo la cuarta parte más movida pasó de 0,83 (Q3). La distancia entre Q1 y Q3 —el rango intercuartil, aquí 0,13— es otra medida de dispersión, y de las buenas: dice «cómo de ancha es la mitad central de las canciones» e ignora por completo los valores raros de los dos extremos, igual de terca que la mediana. Cuando quieras describir un grupo sin que un valor loco te descuadre el retrato, tira de cuartiles.
(Un aviso de aritmética: si restas las cifras redondeadas —0,83 menos 0,71— te sale 0,12, no el 0,13 impreso. No hay error: el rango se calcula con los cuartiles sin redondear, \(0{,}833 - 0{,}706 = 0{,}127\). Es la regla de siempre: redondea al final, nunca en medio.)
Ahora sí, la música de verdad
Basta de listas de juguete. Trae el catálogo real —el mismo musica.csv que descargaste y limpiaste en las misiones anteriores, ya servido en tu cuaderno— y hazle la primera pregunta seria. Cada fila es una canción con su danceability ya medida, del 0 al 1; no hay que promediar nada para tener un número por canción, ya viene puesto de fábrica.
import pandas as pd
musica = pd.read_csv("musica.csv")
print("Canciones en el catalogo:", len(musica))
print("Generos distintos:", musica["track_genre"].nunique())Canciones en el catalogo: 3351
Generos distintos: 114
Tres mil trescientas cincuenta y una canciones, repartidas en 114 géneros. Antes de enfrentar el reggaeton contra el resto, un analista honesto mira el panorama entero: ¿qué géneros son, de verdad, los más bailables? Ese groupby que aprendiste con pandas en la Misión 3 hace aquí un trabajo precioso: agrupa todas las canciones de cada género y les saca la media de danceability, dejándote un solo número por género. Ordénalos de mayor a menor y asómate a la cima:
ranking = (musica.groupby("track_genre")["danceability"]
.mean().sort_values(ascending=False).round(3))
print(ranking.head(5))track_genre
chicago-house 0.792
kids 0.781
latin 0.776
dancehall 0.774
reggaeton 0.772
Name: danceability, dtype: float64
Sorpresa, y de las que a un juez le encantan: el reggaeton, con 0,772 de media, es muy bailable… pero no el más bailable. Va el quinto. Por delante tiene el chicago-house, la música infantil (kids), el latin y el dancehall. O sea: si tu pregunta fuera «¿es el reggaeton el más bailable de todos?», la respuesta honrada sería no. Pero el encargo pregunta otra cosa —«¿es más bailable que el resto?»—, y esas dos preguntas no son la misma. Guárdate esta distinción, que es de juez: se responde a la pregunta que te hacen, ni una más ni una menos. Para el encargo, parte el catálogo en dos: el reggaeton por un lado, y todo lo demás —los otros 113 géneros— por el otro, ese «resto» contra el que compites.
reggaeton = musica[musica["track_genre"] == "reggaeton"]["danceability"]
resto = musica[musica["track_genre"] != "reggaeton"]["danceability"]
for nombre, grupo in [("Reggaeton", reggaeton), ("Resto", resto)]:
print(nombre,
"-> canciones:", len(grupo),
" media:", round(grupo.mean(), 2),
" mediana:", round(grupo.median(), 2),
" desviacion:", round(grupo.std(), 2))Reggaeton -> canciones: 30 media: 0.77 mediana: 0.8 desviacion: 0.08
Resto -> canciones: 3321 media: 0.58 mediana: 0.59 desviacion: 0.17
Léelo despacio, que hay mucho. El reggaeton tiene 30 canciones, con una media de 0,77 y una mediana de 0,80 muy cerca —señal de que las canciones de reggaeton son bastante parejas entre sí, sin locuras—. El resto son 3321 canciones, con media 0,58: mucho menos bailables, en conjunto. Y fíjate en la dispersión: la del resto (0,17) es más del doble que la del reggaeton (0,08). Lógico: el «resto» mezcla clásica, metal, jazz, ambient… de todo; el reggaeton es un género apretado, casi siempre en la zona alta del baile.
Ese bucle a mano está muy bien para entender qué calculas, pero pandas te da todo el retrato de un grupo —centro, dispersión y cuartiles— en una sola orden, describe. Es el atajo que resume esta sección entera:
resumen = pd.DataFrame({"reggaeton": reggaeton.describe(),
"resto": resto.describe()}).round(2)
print(resumen) reggaeton resto
count 30.00 3321.00
mean 0.77 0.58
std 0.08 0.17
min 0.63 0.00
25% 0.71 0.47
50% 0.80 0.59
75% 0.83 0.70
max 0.91 0.98
En ocho renglones tienes la ficha completa de los dos grupos: cuántas canciones (count), la media (mean), la desviación típica (std), el mínimo y el máximo, y los tres cuartiles (25%, 50% —la mediana— y 75%). Mira el dato que más grita: la canción menos bailable de todo el reggaeton marca 0,63 (min), y sin embargo el resto baja hasta 0,00 (min) —algún tema ambient o de estudio, imposible de bailar—. O sea: el reggaeton más soso sigue siendo más bailable que un montón de canciones del resto. Ya intuyes la respuesta —el reggaeton pide más pista—, pero un juez no sentencia con una intuición. Falta ponerle número a la duda. Antes, mírales la cara a esos dos grupos.
La figura 6.1 dibuja los dos grupos. Cada barra cuenta qué proporción de canciones cae en cada franja de danceability. Y salta a la vista lo que los números insinuaban: la montaña del reggaeton vive más a la derecha, apretada en la zona bailable, mientras la del resto se desparrama de 0 a casi 1. Cuando dos grupos se separan así de claro, la respuesta va a ser fácil. Pero —y aquí viene la lección grande— no siempre se separan tanto. A veces las dos montañas se solapan casi del todo, y entonces el ojo ya no basta. Para esos casos necesitas una herramienta que mida la duda. Vamos a por ella con un experimento que parece un juego.
Una diferencia puede ser pura suerte
Este es el corazón de la misión, así que léelo dos veces. Vamos a demostrar algo que suena imposible: que puedes coger un solo montón de canciones, sin ninguna diferencia real por dentro, partirlo en dos al azar… y que las dos mitades tengan danceability media distinta. Diferencias que salen de la nada, solo porque el azar reparte desigual. Si entiendes esto, no vuelves a tragarte una diferencia pequeña en tu vida.
El experimento: fabricamos 60 canciones que vienen todas del mismo sitio (así, por construcción, no hay diferencia real que encontrar), las barajamos y las repartimos en dos grupos de 30 —justo el tamaño del grupo del reggaeton—. Como en la Misión 1, fijamos la semilla del azar con default_rng(2026) para que a ti te salga exactamente lo mismo que aquí —esa es la reproducibilidad de siempre—.
import numpy as np
rng = np.random.default_rng(2026)
pot = rng.normal(0.58, 0.17, 60).round(2) # 60 canciones del MISMO monton
rng.shuffle(pot) # barajar
g1 = pot[:30].mean() # primeras 30
g2 = pot[30:].mean() # ultimas 30
print("Grupo 1:", round(g1, 2), " Grupo 2:", round(g2, 2))
print("Diferencia inventada:", round(g1 - g2, 2))Grupo 1: 0.59 Grupo 2: 0.65
Diferencia inventada: -0.06
¡Una diferencia de 0,06 salida de la nada! Los dos grupos son el mismo tipo de canción —no hay ningún «grupo más bailable»—, y aun así uno marca 0,59 y el otro 0,65. No es un error: es el azar repartiendo. Si te hubieran dado solo esos dos grupos, sin saber su origen, habrías podido jurar que el segundo es «más bailable». Y habrías hecho el ridículo. Ahora bien, ¿este 0,06 fue mala suerte de una vez, o el azar siempre inventa diferencias así de gordas? Para saberlo, no lo hagas una vez: hazlo diez mil, y mira qué tamaño tienen esas diferencias inventadas.
rng = np.random.default_rng(2026)
pot = rng.normal(0.58, 0.17, 60).round(2)
difs = []
for _ in range(10000):
rng.shuffle(pot)
difs.append(pot[:30].mean() - pot[30:].mean())
difs = np.array(difs)
print("Repartos probados:", len(difs))
print("Diferencia tipica por puro azar:", round(difs.std(), 2))
print("La mayor diferencia por azar: ", round(np.abs(difs).max(), 2))Repartos probados: 10000
Diferencia tipica por puro azar: 0.04
La mayor diferencia por azar: 0.17
Aquí está la lección que convierte a un crédulo en un juez. Repartiendo al azar diez mil veces el mismo montón sin diferencias, las medias de las dos mitades se separaron típicamente unas 0,04 unidades, y en algún reparto con muy mala suerte llegaron a separarse 0,17. O sea: por puro azar, sin nada real detrás, aparecen diferencias de hasta 0,17. Piensa en lo que eso significa. Si mañana comparas dos géneros y te sale una diferencia de 0,04, o de 0,08, o incluso de 0,15, no puedes gritar victoria: el azar solito produce diferencias de ese tamaño a todas horas. Solo cuando la diferencia es tan grande que el azar jamás la produciría —como los 0,19 del reggaeton contra el resto, más grandes que la mayor que fabricó el azar en diez mil intentos— puedes sentenciar sin miedo. La pregunta clave de todo analista honesto queda por fin formulada: ¿es mi diferencia más grande que las que inventa la casualidad?
La figura 6.2 dibuja esas diez mil diferencias inventadas: forman una campana centrada en el cero (lo normal, cuando no hay diferencia real, es que no haya diferencia), que se estira hasta más o menos \(\pm 0{,}13\) y muy de vez en cuando llega a 0,17. Ahí, sobre ese mismo dibujo, marca dónde caen tus dos casos de verdad. La diferencia del reggaeton contra el reggae (\(+0{,}01\)) cae en plena campana, entre las diferencias que el azar fabrica a diario: indistinguible de la casualidad. La del reggaeton contra el resto (\(+0{,}19\)) se sale tanto del dibujo que hay que señalarla con una flecha —el azar no llega ahí ni en un millón de intentos—. Esa es, en una sola imagen, la pregunta de toda la misión: ¿cae tu diferencia dentro de la campana del azar, o se escapa de ella?
El margen: no me fío del último dígito
Ese temblor del azar tiene una consecuencia preciosa, y es la idea más importante que te llevas de esta misión: ningún número medido es exacto. Cuando dices «la media del reggaeton es 0,77», no quieres decir que sea clavado 0,77. Si hubieras cogido otras 30 canciones de reggaeton distintas te habría salido 0,76, o 0,78, algo cercano pero no idéntico. El último dígito baila. Un analista honesto no esconde ese baile: lo declara. A ese «más o menos» se le llama margen, y la forma de decirlo es: «la media es 0,77, y no me fío del último dígito; el de verdad anda a menos de 0,04 de aquí».
¿De dónde sale el tamaño del margen? De dos cosas con todo el sentido del mundo:
De cuánto se dispersan los datos. Si las canciones de reggaeton fueran todas casi igual de bailables, la media sería firmísima. Si fueran una montaña rusa, temblaría más. Más dispersión, más margen.
De cuántos datos tienes. Con tres canciones, tu media es un rumor. Con treinta, es un dato serio. Cuantas más midas, más se afina la media y más pequeño el margen. Medir más es comprar certeza.
Juntando las dos ideas sale una cuenta que los estadísticos llaman error estándar, y que multiplicada por un factor fijo (1,96, ya verás por qué en la caja) te da el margen de fiar del 95 %. No necesitas entender la fórmula para usarla; envuélvela en una función y olvídate de las tripas:
import numpy as np
def margen(grupo):
error = grupo.std() / np.sqrt(len(grupo))
return 1.96 * error
print("Reggaeton:", round(reggaeton.mean(), 2),
"+-", round(margen(reggaeton), 2))
print("Resto: ", round(resto.mean(), 2),
"+-", round(margen(resto), 2))Reggaeton: 0.77 +- 0.03
Resto: 0.58 +- 0.01
Ya tienes tus dos números con su duda puesta. La media del reggaeton es 0,77, más o menos 0,03: el valor de verdad está, casi con seguridad, entre 0,74 y 0,80. La del resto, 0,58 más o menos 0,01: entre 0,57 y 0,59. Fíjate en lo distinto que es cada margen —el del reggaeton es unas cinco veces el del resto— porque el resto son 3321 canciones y el reggaeton solo 30: muchos más datos afinan mucho más. Ese «\(0{,}77 \pm 0{,}03\)» se llama, en cristiano de analista, un intervalo de confianza, y es la manera honrada de dar cualquier resultado medido. Nunca un número pelado: siempre un número con su margen.
¿Cuántos datos hacen falta?
De las dos cosas que mueven el margen —la dispersión y la cantidad de datos—, la segunda está en tus manos: siempre puedes reunir más canciones. Pero, ¿cuánto ayuda cada canción nueva? Aquí hay una sorpresa que conviene conocer antes de ponerte a recoger datos como un poseso. Deja fija la dispersión (pongamos la del reggaeton, 0,08) y mira cómo encoge el margen según cuántas canciones midas:
import numpy as np
for n in [5, 10, 30, 100, 300]:
margen = 1.96 * 0.08 / np.sqrt(n)
print("Con", n, "canciones -> margen +-", round(margen, 2))Con 5 canciones -> margen +- 0.07
Con 10 canciones -> margen +- 0.05
Con 30 canciones -> margen +- 0.03
Con 100 canciones -> margen +- 0.02
Con 300 canciones -> margen +- 0.01
La primera lección es la que esperabas: más datos, menos margen. Con 5 canciones tu media tiembla en \(\pm 0{,}07\); con 30, en \(\pm 0{,}03\); con 300, en \(\pm 0{,}01\). Pero mira los saltos con lupa y verás la trampa escondida: pasar de 5 a 30 canciones (seis veces más trabajo) baja el margen de 0,07 a 0,03, un recorte enorme; en cambio, pasar de 30 a 300 (diez veces más trabajo) solo lo baja de 0,03 a 0,01. Cada dato nuevo afina menos que el anterior. Es la raíz cuadrada de la fórmula del margen haciendo de las suyas: para partir el margen por la mitad no basta con el doble de datos, hacen falta cuatro veces más. Por eso un analista listo no persigue la certeza absoluta —costaría infinito—: recoge datos hasta que el margen sea lo bastante pequeño para contestar su pregunta, y ahí para. Con 30 canciones de reggaeton y un margen de 0,03, la pregunta del encargo estaba más que servida.
Redondear con honradez
El margen tiene una consecuencia práctica que casi nadie respeta y que a ti te va a distinguir: te dice cuántas cifras tienes derecho a enseñar. Cuando el ordenador calcula la diferencia reggaeton-resto, escupe algo como 0.19197. Da la tentación de copiarlo tal cual —parece más científico—. Pero es justo lo contrario: es mentir con precisión falsa. Si tu margen es 0,03, el tercer decimal (el 1 de 0,191) ya está bailando, y el resto es puro ruido. Enseñarlos es fingir una exactitud que no tienes.
diferencia = 0.19197
margen = 0.03
print("Cifra cruda:", diferencia)
print("Cifra honrada:", round(diferencia, 2), "+-", margen)Cifra cruda: 0.19197
Cifra honrada: 0.19 +- 0.03
La regla del analista honrado: redondea el resultado hasta donde el margen deja de temblar. Con un margen de 0,03, la respuesta es «0,19», dos decimales —más allá, inventas—. Un titular que presume de «un 19,197 % más bailable» está, sin saberlo, gritando que quien lo escribió no entiende sus propios datos. Ya lo hiciste sin darte cuenta con round(dif, 2) en cada listado de esta misión; ahora sabes que ese round no era por comodidad: era por honradez. Precisión de más es una forma de engaño tan fea como la falta de margen.
Comparar dos grupos con honestidad
Ya tienes todas las piezas. Comparar dos grupos con honestidad es, resumido, esto: no mires solo si sus medias difieren —difieren casi siempre—, mira si sus márgenes se pisan. Si los dos intervalos se solapan, los grupos podrían ser el mismo y el azar; si están claramente separados, la diferencia es de fiar. La forma más limpia de decidirlo es mirar la diferencia de las dos medias con su propio margen y preguntar una sola cosa: ¿el cero cae dentro de ese margen?
dif = reggaeton.mean() - resto.mean()
error_dif = np.sqrt(reggaeton.std()**2 / len(reggaeton)
+ resto.std()**2 / len(resto))
margen_dif = 1.96 * error_dif
print("Diferencia:", round(dif, 2), "+-", round(margen_dif, 2))
print("Entre", round(dif - margen_dif, 2),
"y", round(dif + margen_dif, 2))Diferencia: 0.19 +- 0.03
Entre 0.16 y 0.22
La diferencia entre reggaeton y resto es de 0,19, y su margen es 0,03: está, casi con seguridad, entre 0,16 y 0,22. ¿Cae el cero ahí dentro? Ni de lejos —el intervalo entero está muy por encima de cero—. Traducción: es imposible que esta diferencia sea casualidad. El reggaeton es más bailable que el resto, y punto. Compáralo con lo que aprendiste antes: el azar inventaba diferencias de hasta 0,17; esta es de 0,19, con margen de 0,03. No hay partido.
Pero un juez de verdad se pone a prueba con un caso difícil, no solo con el fácil. Coge dos géneros que deberían parecerse —el reggaeton y el reggae, el ritmo caribeño del que nació el reggaeton— y aplícales la misma vara:
reggae = musica[musica["track_genre"] == "reggae"]["danceability"]
dif = reggaeton.mean() - reggae.mean()
error = np.sqrt(reggaeton.std()**2 / len(reggaeton)
+ reggae.std()**2 / len(reggae))
print("Reggaeton:", round(reggaeton.mean(), 2),
" Reggae:", round(reggae.mean(), 2))
print("Diferencia:", round(dif, 2), "+-", round(1.96 * error, 2))
print("Entre", round(dif - 1.96*error, 2),
"y", round(dif + 1.96*error, 2))Reggaeton: 0.77 Reggae: 0.76
Diferencia: 0.01 +- 0.04
Entre -0.03 y 0.05
Aquí está la otra cara, y es la que separa a un juez de un fanfarrón. Reggaeton marca 0,77 y reggae 0,76: son distintos, el reggaeton parece un pelín más bailable. Un crédulo titularía «¡el reggaeton supera al reggae del que nació!». Pero mira el margen: la diferencia es \(0{,}01\) con un margen de 0,04, o sea, en algún punto entre \(-0{,}03\) y \(0{,}05\). Y el cero cae de lleno dentro de ese intervalo. Eso significa que la diferencia de 0,01 cabe entera dentro del temblor del azar: es perfectamente posible que reggaeton y reggae bailen igual y que ese 0,01 sea puro reparto de la suerte, como los que fabricabas antes. La respuesta honrada no es «el reggaeton gana» ni «el reggae gana». Es la respuesta más valiente de un analista: «no se puede decidir». Fíjate en la figura 6.3: el reggaeton contra el resto vive en otro planeta, pero reggaeton y reggae se pisan los márgenes por completo.
La victoria
Tienes todas las piezas: media y mediana, dispersión, el temblor del azar, el margen y la comparación honesta. Hora de juntarlas en una sola herramienta que conteste el encargo como lo haría un juez del dato. Vamos a escribir una función compara que reciba dos grupos y devuelva un veredicto completo: quién es más bailable, por cuánto, con qué margen —y, si el margen cruza el cero, la honradez de declarar que no se puede decidir—.
import numpy as np
def compara(grupo_a, grupo_b, nombre_a, nombre_b):
dif = grupo_a.mean() - grupo_b.mean()
error = np.sqrt(grupo_a.std()**2 / len(grupo_a)
+ grupo_b.std()**2 / len(grupo_b))
margen = 1.96 * error
bajo, alto = dif - margen, dif + margen
if bajo > 0: # el intervalo entero por encima de 0
mas = nombre_a
elif alto < 0: # el intervalo entero por debajo de 0
mas = nombre_b
else: # el cero cae dentro: no hay veredicto
mas = "no se puede decidir"
return {
"mas_bailable": mas,
"diferencia": round(float(dif), 2),
"margen": round(float(margen), 2),
"entre": (round(float(bajo), 2), round(float(alto), 2)),
}
parte = compara(reggaeton, resto, "reggaeton", "resto")
for clave, valor in parte.items():
print(clave, "->", valor)mas_bailable -> reggaeton
diferencia -> 0.19
margen -> 0.03
entre -> (0.16, 0.22)
Ahí está tu veredicto, y es de juez. No dice «el reggaeton es más bailable» a secas —eso lo dice cualquiera—. Dice: el reggaeton es más bailable que el resto por 0,19 puntos de danceability de media, con un margen de solo 0,03, así que la diferencia real está entre 0,16 y 0,22. Como toda esa franja queda por encima de cero, la sentencia es firme: sí, el reggaeton es más bailable, sin lugar a la duda. Has contestado el encargo con las tres cosas que lo hacen honesto: cuánto, con qué margen y si es de fiar. Y lo mejor: la misma función, sin tocar una línea, sabría decirte «no se puede decidir» ante un caso dudoso. Eso —saber cuándo callar— es lo que de verdad te convierte en juez del dato.
¿Lo lograste?
Como en cada misión, no te fías de que «parece que va»: lo compruebas. Esta celda verifica de golpe las dos caras del oficio —que el caso claro se sentencia y que el caso dudoso se declara indeciso—. Si los tres guardianes callan, has vencido:
parte = compara(reggaeton, resto, "reggaeton", "resto")
assert parte["mas_bailable"] == "reggaeton", "Revisa el signo de la diferencia."
assert parte["entre"][0] > 0, "El margen debe quedar por encima de cero."
reggae = musica[musica["track_genre"] == "reggae"]["danceability"]
control = compara(reggaeton, reggae, "reggaeton", "reggae")
assert control["mas_bailable"] == "no se puede decidir", \
"Reggaeton y reggae no se distinguen."
print("Lo lograste. Insignia desbloqueada: juez del dato.")Lo lograste. Insignia desbloqueada: juez del dato.
Si ves ese mensaje, enhorabuena de las grandes: has aprendido a medir sin engañarte. Sabes resumir con honradez (media y mediana), medir la dispersión, reconocer que una diferencia puede ser azar, ponerle a cada número su margen y —lo más difícil— decidir cuándo una diferencia cuenta y cuándo hay que callarse. Te has ganado la insignia juez del dato. Si en cambio salta un aviso, no es un fracaso: es el guardián haciendo su trabajo. Casi siempre el fallo está en un signo (¿restaste al revés?) o en un margen; revísalo con calma y vuelve a probar. Nadie mira; solo tú y el problema.
La bitácora del analista
Abre tu bitácora —esa que arrancó en la Misión 1— y anota esta victoria, que es de las que marcan. Para la Misión 6, escribe al menos:
La pregunta: «¿de verdad el reggaeton es más bailable que el resto?».
El veredicto, con sus tres partes: sí, es más bailable; por 0,19 de media; con un margen de 0,03 (entre 0,16 y 0,22). Una respuesta de juez, no una opinión. Y la coletilla honrada: más bailable que el resto, sí, pero no el más bailable de todos (va quinto en el ranking).
El contraejemplo que te enseñó a dudar: reggaeton contra reggae, «no se puede decidir». Apúntalo, porque es la lección que más te va a servir: reconocer cuándo una diferencia no cuenta.
Una idea que te haya reordenado la cabeza: ¿te sorprendió que el azar inventara diferencias de hasta 0,17 de la nada? ¿Que la media y la mediana contaran historias distintas?
Un consejo de analista veterano: la próxima vez que oigas un titular con una cifra —«tal canción es un 3 % más pegadiza», «este grupo es el más bailable»—, hazte por dentro la pregunta de esta misión: ¿con qué margen? ¿podría ser azar?. La mayoría de los titulares no lo dicen. Tú, a partir de hoy, ya no te los tragas enteros.
Sube de nivel: la mediana también juzga
La victoria la ganaste comparando medias. Pero acuérdate de la trampa del principio: la media se deja arrastrar por los valores locos. ¿Y si una canción con un dato roto —de esas que cazaste en la Misión 4, con la danceability disparada por un error— se colara en el reggaeton? Míralo:
regg_roto = list(reggaeton.values) + [5.0] # una cancion con dato roto
print("Media original:", round(reggaeton.mean(), 2),
" con el dato roto:", round(np.mean(regg_roto), 2))
print("Mediana original:", round(reggaeton.median(), 2),
" con el dato roto:", round(np.median(regg_roto), 2))Media original: 0.77 con el dato roto: 0.91
Mediana original: 0.8 con el dato roto: 0.8
Un solo dato roto (5,0, imposible en una escala de 0 a 1) empujó la media de 0,77 a 0,91, mientras que la mediana no se movió (0,80). Es la lección de la mediana, ahora con datos de verdad: resiste. Por eso un analista cuidadoso, cuando sospecha que hay valores extremos, mira también la comparación de medianas, no solo la de medias. Si las dos dan el mismo veredicto —y aquí lo darían—, te fías el doble. Si discrepan, ahí hay un valor escondido que merece que lo investigues antes de sentenciar.
Otra comparación de verdad: reggaeton contra rock
Y ya que tienes la herramienta compara montada, dale otra pregunta que importa. Nuestro catálogo no es solo reggaeton: en el otro extremo del baile está el rock, todo guitarras y batería, más para mover la cabeza que la cintura. ¿De verdad es el reggaeton más bailable que el rock? Compáralos con la misma vara honesta:
rock = musica[musica["track_genre"] == "rock"]["danceability"]
print(compara(reggaeton, rock, "reggaeton", "rock")){'mas_bailable': 'reggaeton', 'diferencia': 0.18, 'margen': 0.05, 'entre': (0.12, 0.23)}
Veredicto: sí, el reggaeton es más bailable que el rock, por 0,18 de media, con la franja (0,12 a 0,23) entera por encima de cero —diferencia de fiar—. Ojo a la escala: aquí el margen (0,05) es mayor que el del encargo (0,03), porque el rock son solo 29 canciones y el «resto» eran 3321. Menos datos, más margen —pero la diferencia sigue siendo tan grande que el margen no la alcanza—. Eso es lo bonito del método: no necesitas siempre miles de datos, necesitas que la diferencia sea más grande que su propia duda.
Un caso más justo: reggaeton contra funk
Los dos casos anteriores eran cómodos: el resto y el rock, muy por debajo. El oficio de verdad está en los rivales de peso, los que no se ven a ojo. Aquí va uno: el funk nació para bailar —puro ritmo y bajo—. ¿Es el reggaeton más bailable que el funk? Antes de ejecutar, apuesta:
funk = musica[musica["track_genre"] == "funk"]["danceability"]
print(compara(reggaeton, funk, "reggaeton", "funk")){'mas_bailable': 'reggaeton', 'diferencia': 0.08, 'margen': 0.07, 'entre': (0.02, 0.15)}
Este sí que es interesante. El reggaeton es más bailable por 0,08… pero mira el margen: 0,07, casi tan grande como la propia diferencia. El intervalo va de 0,02 a 0,15; se queda por encima de cero —por poco—, así que la respuesta honrada es «sí, el reggaeton es un pelín más bailable que el funk, pero con mucha menos seguridad que contra el rock, y por un margen que casi lo roza». Un juez de verdad no da todas sus sentencias con la misma firmeza: la del resto era un mazazo; esta es un «sí, pero con la voz más baja». Y si cambiaras solo unas canciones o midieras otras 30, podría darse la vuelta. Saber graduar la confianza —no solo tenerla o no tenerla— es la señal de que ya piensas como un analista.
(Si restas las cifras redondeadas no te saldrá exactamente el intervalo: la función calcula los extremos antes de redondear, que es lo honrado. Es la misma regla de la sección anterior —redondea al final, nunca en medio— puesta en práctica.)
Comparar no solo medias: cuenta con margen
Hasta ahora comparabas medias. Pero a veces la pregunta es de contar, no de promediar: ¿cuántas canciones son de fiesta de verdad, tan bailables que nadie se queda sentado? Pongamos el listón en 0,7 de danceability. Esa cuenta también se puede comparar entre reggaeton y resto… y también merece su margen, porque un porcentaje medido tiembla igual que una media. La cuenta buena es la proporción de canciones de fiesta, y su margen sale de una fórmula prima de la del intervalo de confianza:
import numpy as np
def de_fiesta(grupo, limite=0.7):
alta = grupo > limite
p = alta.mean() # proporcion de fiesta (0 a 1)
margen = 1.96 * np.sqrt(p * (1 - p) / len(grupo))
return 100 * p, 100 * margen
for nombre, g in [("Reggaeton", reggaeton), ("Resto", resto)]:
p, m = de_fiesta(g)
print(nombre, "-> de fiesta:", round(p, 1), "% +-", round(m, 1))Reggaeton -> de fiesta: 76.7 % +- 15.1
Resto -> de fiesta: 26.0 % +- 1.5
Otra forma de contar la misma verdad, y contundente: en el reggaeton tres de cada cuatro canciones (76,7 %) pasan del listón de fiesta; en el resto, una de cada cuatro (26,0 %). Pero fíjate en el margen del reggaeton: \(\pm 15{,}1\), enorme. ¿Por qué? Porque solo son 30 canciones: con tan pocas, hasta un porcentaje baila mucho. El del resto (\(\pm 1{,}5\)) es diez veces más fino, porque son 3321. La próxima vez que leas «el 77 % de tal cosa», sabrás preguntar lo de siempre: ¿de cuántos casos? ¿con qué margen?.
Cinco maneras de engañarte (y cómo esquivarlas)
Ya eres juez del dato, pero un buen juez conoce los trucos de los tramposos —empezando por el tramposo que todos llevamos dentro cuando un resultado nos gusta demasiado—. Aquí tienes las cinco formas más comunes de engañarse con números. La buena noticia: ya sabes esquivar casi todas.
1. Confundir el azar con una señal.
La reina de las trampas, y la que más has practicado hoy: ver una diferencia pequeña y creerla real. El antídoto ya es tuyo —el margen—: si el intervalo de la diferencia toca el cero (como en el reggaeton contra el reggae, 0,01), te callas.
2. Olvidar la dispersión.
Dar solo el centro y esconder el desparrame. «La danceability media de esta lista es 0,6» no dice si todas rondaron 0,6 o si mezcla baladas de 0,2 y temazos de 0,95: son dos listas muy distintas con la misma media. El antídoto: un centro nunca viaja solo.
3. Fiarte de una muestra minúscula.
«Escuché tres canciones de ese grupo y son un peñazo.» Con tres datos, el margen es un océano —acabas de ver que el reggaeton, con solo 30 canciones, ya arrastra un margen del 15 % en la cuenta de fiesta—. El antídoto: mira cuántos datos sostienen una cifra antes de creértela.
4. Probar hasta que salga (la peor de todas).
Esta es sutil y hace un daño enorme, así que vamos a pillarla con las manos en la masa. Recuerda que un margen del 95 % se equivoca, por diseño, una de cada veinte veces: una de cada veinte veces grita «¡hay diferencia!» donde no la hay. Normalmente no pasa nada… salvo que te dediques a probar muchas comparaciones y te quedes solo con la que «salió». Mira mil comparaciones entre grupos sin ninguna diferencia real:
import numpy as np
rng = np.random.default_rng(2026)
pruebas = 1000
falsos = 0
for _ in range(pruebas):
pot = rng.normal(0.58, 0.17, 60) # sin diferencia real
rng.shuffle(pot)
a, b = pot[:30], pot[30:]
dif = a.mean() - b.mean()
error = np.sqrt(a.std(ddof=1)**2 / 30 + b.std(ddof=1)**2 / 30)
if dif - 1.96 * error > 0 or dif + 1.96 * error < 0:
falsos += 1 # el intervalo NO toca el cero
print("Pruebas sin diferencia real:", pruebas)
print("Veces que 'salio diferencia':", falsos)
print("Porcentaje:", round(100 * falsos / pruebas, 1))Pruebas sin diferencia real: 1000
Veces que 'salio diferencia': 59
Porcentaje: 5.9
Cincuenta y nueve veces de mil —un 5,9 %, casi el «uno de cada veinte» prometido— el azar fabricó una diferencia tan grande que su intervalo se saltó el cero. Ninguna era real; todas eran suerte. Ahora imagina a alguien que compara los 114 géneros entre sí (¡miles de parejas!) buscando «cuál es distinto», y luego titula solo con el que le salió. Habrá encontrado un falso hallazgo casi con seguridad, y jurará que es verdad. El antídoto es de hierro: decide qué vas a comparar antes de mirar los datos, y desconfía del hallazgo que aparece después de mucho rebuscar. Buscar hasta que algo «salga» no es investigar: es engañarse con método.
5. Confundir «de fiar» con «importante».
Con muchísimos datos, diferencias diminutas y sin ninguna trascendencia pueden salir «de fiar» —el margen se encoge tanto que hasta un cambio ridículo deja de tocar el cero—. Que dos cosas se distingan con seguridad no significa que la diferencia valga la pena. El antídoto: mira siempre el tamaño de la diferencia, no solo si es de fiar. Los 0,19 del reggaeton importan; dos milésimas (reggaeton contra dancehall), aunque fueran de fiar, no le cambian la fiesta a nadie.
Cinco trampas, cinco antídotos, y todos caben en una sola frase que ya es tuya: pide el margen, mira el tamaño y decide antes de mirar. Repítela como un conjuro cada vez que alguien te ponga delante una cifra.
El jefe de parte: un veredicto para cualquier pregunta
Hora de enfrentarte al jefe de parte, el miniproyecto que cierra la misión. El encargo del jefe es convertir tu compara en una herramienta de comunicar, no solo de calcular: una función que, dada una comparación, escupa una frase que cualquiera entienda —tu abuela, un periodista, tú dentro de un año—. Porque un veredicto que solo entiende quien lo calculó no sirve de nada. Reutiliza el diccionario que ya devuelve compara y tradúcelo a español:
def veredicto(grupo_a, grupo_b, nombre_a, nombre_b):
r = compara(grupo_a, grupo_b, nombre_a, nombre_b)
if r["mas_bailable"] == "no se puede decidir":
return (f"No se puede decidir entre {nombre_a} y {nombre_b} "
f"(diferencia {r['diferencia']}, margen {r['margen']}).")
return (f"{r['mas_bailable'].capitalize()} es mas bailable, por "
f"{abs(r['diferencia'])} de media (margen {r['margen']}; "
f"entre {r['entre'][0]} y {r['entre'][1]}).")
print(veredicto(reggaeton, resto, "reggaeton", "resto"))
print(veredicto(reggaeton, reggae, "reggaeton", "reggae"))Reggaeton es mas bailable, por 0.19 de media (margen 0.03; entre 0.16 y 0.22).
No se puede decidir entre reggaeton y reggae (diferencia 0.01, margen 0.04).
Mira lo que has fabricado: una sola función que, le eches lo que le eches, devuelve una frase honrada —con su cuánto, su margen y, cuando toca, la valentía de decir «no se puede decidir»—. Ya no es un cálculo: es un juez portátil. Le das dos grupos y te dicta sentencia en un español que no engaña a nadie. Eso es, en miniatura, el oficio entero de la misión.
¿Lo lograste? (nivel jefe)
El jefe también se comprueba. Esta celda exige que las dos frases digan lo que deben —la firme para el reggaeton contra el resto, la prudente para reggaeton y reggae—:
f1 = veredicto(reggaeton, resto, "reggaeton", "resto")
f2 = veredicto(reggaeton, reggae, "reggaeton", "reggae")
assert "Reggaeton es mas bailable" in f1, "El reggaeton debe ganar."
assert "No se puede decidir" in f2, "Reggaeton y reggae no se distinguen."
print("Parte validado. Eres juez del dato.")Parte validado. Eres juez del dato.
Dos frases, dos comprobaciones, un solo mensaje de victoria. Si los guardianes callan, tu juez portátil funciona: sentencia lo seguro y se muerde la lengua ante lo dudoso. No lo crees porque «parece bien»; lo sabes porque lo has comprobado. Ese es, otra vez, el oficio entero en miniatura.
El cuadro de tus sentencias
Antes de los retos, mira atrás. A lo largo de la misión has juzgado cuatro comparaciones con la misma vara honesta, y merece la pena verlas juntas en la tabla 6.1: es el resumen de todo lo que sabes hacer ahora.
| Comparación | Diferencia | Margen | Veredicto |
|---|---|---|---|
| Reggaeton vs. resto | 0,19 | 0,03 | de fiar (y enorme) |
| Reggaeton vs. rock | 0,18 | 0,05 | de fiar |
| Reggaeton vs. funk | 0,08 | 0,07 | de fiar, por poco |
| Reggaeton vs. reggae | 0,01 | 0,04 | no se puede decidir |
Léela de arriba abajo y verás la lección grande de la misión en cuatro renglones. El reggaeton contra el resto gana por goleada; contra el rock, por una diferencia casi igual de grande y con un margen algo mayor, pero de fiar; contra el funk, por una diferencia mucho más pequeña y con un margen que casi la alcanza —de fiar, pero por poco—; y contra el reggae se queda en tablas, sin veredicto. Lo que decide no es lo gorda que sea la diferencia, sino si es más grande que su propia duda. Una diferencia de 0,08 con margen 0,07 apenas cuenta; una de 0,01 con margen 0,04 no cuenta nada. Grábate esa tabla: es tu misión entera resumida en una imagen.
Retos: elige tu nivel
Ahora te toca a ti. Los retos suben de dificultad: \(\star\) es imprescindible, \(\star\star\) te reta y \(\star\star\star\) es de jefe. Haz al menos todas las de una estrella; sube hasta donde te apetezca. Y en todas, la regla de oro de esta misión: antes de mirar el resultado, apuesta si la diferencia será de fiar o podría ser azar.
★ Media contra valle. Coge la lista
[0.71, 0.69, 0.70, 0.72, 0.15]y calcula su media y su mediana. ¿Cuál representa mejor «una canción normal» de la lista? Explica en una frase por qué se separan tanto.★ La mediana a mano. Sin usar
np.median, calcula la mediana de[0.7, 0.3, 0.9, 0.1, 0.5]ordenando y cogiendo el del medio. Luego compruébala connp.median. ¿Coinciden?★ Rango de un género. Toma un género cualquiera con
musica[musica["track_genre"] == "salsa"]["danceability"]e imprime su valor máximo, su mínimo y el rango (la resta). ¿Cuánto varía lo bailable dentro de la salsa?★ Mismo centro, distinta alma. Inventa dos listas de cinco danceabilities con la misma media pero dispersiones muy distintas. Compruébalo con
np.meanynp.std. Acabas de recrear las dos listas de reproducción.★★ Latin contra latino. Repite la comparación de la victoria, pero enfrentando el género
latincontralatino. Antes de ejecutar, apuesta: ¿saldrá una diferencia de fiar o un «no se puede decidir»?★★ El margen a mano. Sin usar tu función
margen, calcula el intervalo del reggaeton con la fórmula de la caja:media +- 1.96 * desviacion / raiz(n). Debe darte \(0{,}77 \pm 0{,}03\). Si cuadra, has entendido de dónde sale el margen.★★ Cuantas más, más fino. Calcula el margen del reggaeton usando solo las primeras 10 canciones (
reggaeton.iloc[:10]) y compáralo con el de las 30. ¿Cuánto se ensancha el margen al medir menos? Comprueba con tus manos la regla «más datos, menos duda».★★ Fabrica azar. Copia el experimento de las diez mil barajadas, pero cambia la semilla a
default_rng(7). ¿Cambia mucho la «diferencia típica por azar»? ¿Qué te dice eso sobre lo robusta que es la conclusión?★★ ¿Explícitas o no? Separa el reggaeton en canciones explícitas y no explícitas (con la columna
explicit) y pásalas porcompara. ¿Se nota la diferencia de baile, o el margen se la traga?★★★ El jefe: comparar medianas. Escribe una versión de
comparaque use la mediana en vez de la media (el margen de una mediana se saca mejor con el bootstrap de la caja). Aplícala a reggaeton contra resto: ¿mismo veredicto? Si sí, tu conclusión es doblemente sólida.★★★ El jefe: el margen por bootstrap. Adapta el bootstrap de la caja para sacar el margen de la diferencia entre reggaeton y resto (remuestrea los dos grupos, resta sus medias, repite diez mil veces). Compara el intervalo que salga con el \(0{,}19 \pm 0{,}03\) de la fórmula. ¿Coinciden los dos caminos?
★★★ El jefe final: tu propio juicio. Elige tú una pregunta comparativa sobre la música —¿es el trap más bailable que el rock?, ¿la música latina más alegre (
valence) que el metal?, ¿el pop más popular que el jazz?—, prepara los dos grupos, pásalos porveredictoy escribe en tu bitácora la frase que salga, defendiéndola en dos líneas. Un juicio entero, de la pregunta a la sentencia.
¿Te has atascado? En el apéndice C tienes, para cada reto, primero una pista y solo después la solución. Pero el pacto es este: entra ahí después de haberlo intentado de verdad.
Tu caja de herramientas
Mira todo lo que sabes juzgar ahora y hace unas páginas no. Pégala en la bitácora y vuelve a ella cuando dudes ante dos números.
Resumir el centro:
np.mean(datos)(media, se deja arrastrar por los valores locos) ynp.median(datos)(mediana, resiste). Míralas juntas.Medir la dispersión: el rango (
max - min) y la desviación típica (np.std(datos), odatos.std()si es columna de pandas, que divide entre \(n-1\)). Un centro nunca viaja solo.Resumir por grupos:
datos.groupby("track_genre")["col"].mean(), un número por género.El margen del 95 %:
1.96 * desviacion / np.sqrt(n). Más dispersión, más margen; más datos, menos. Un número sin margen es un número desnudo.Comparar con honradez: mira la diferencia de medias con su margen y pregunta ¿cae el cero dentro?. Si sí, «no se puede decidir»; si no, hay veredicto.
Sacar el margen sin fórmula: el bootstrap —remuestrear con
rng.choice(..., replace=True)diez mil veces y mirar el 95 % central—.El valor p: una pista más (
scipy.stats.ttest_ind), nunca un oráculo. Mide «rareza por azar», no importancia.Reproducir el azar:
np.random.default_rng(2026), para que mañana salga lo mismo.
No memorices la lista: úsala. La costumbre de pedir siempre el margen se te va a quedar pegada sola.
Cuando quieras ir en serio
Lo que acabas de aprender —resumir sin distorsionar, estimar con su margen, comparar sin engañarte— es el esqueleto de la estadística entera, la de las carreras y la de los laboratorios. Aquí lo has usado a mano, con funciones que cabían en la pantalla, y para entenderlo está perfecto. Cuando quieras dar el salto, hay un mundo esperándote: scipy y statsmodels traen los contrastes ya hechos y muchos más; los intervalos de confianza tienen versiones para casi todo; y hay libros enteros —empezando por el volumen adulto del que nace este— que cuentan con calma el porqué de cada 1,96 y de cada raíz de \(n\).
Pero antes de correr, quédate con la idea que de verdad importa, la que no caduca: la honestidad de reconocer la duda. La estadística no sirve para tener siempre razón; sirve para saber cuánta razón tienes, y para tener el valor de decir «no lo sé todavía» cuando los datos no alcanzan. En un mundo lleno de gente que grita cifras sin margen —anuncios, titulares, discusiones de internet—, alguien que pregunte con calma «¿con qué margen? ¿podría ser azar?» vale su peso en oro. Ese alguien, desde hoy, eres tú.
Misión 6 completada. Insignia juez del dato, desbloqueada. Has aprendido a medir sin engañarte: a resumir con media y mediana, a mirar la dispersión, a reconocer que una diferencia puede ser azar, a ponerle margen a cada número y a comparar dos grupos con honradez —incluida la honradez de callar cuando no se puede decidir—. Y tienes tu veredicto sobre el reggaeton, firmado y con su margen: es más bailable que el resto (0,19 \(\pm\) 0,03) aunque —seamos honrados hasta el final— no sea el más bailable de todos (va el quinto). En la Misión 7 daremos el salto que llevas esperando: enseñaremos a la máquina a adivinar el género de una canción por su sonido —y, fieles a lo de hoy, no nos creeremos sus aciertos hasta comprobar, con su margen, cómo de buena es—.