# Significativo no es importante

URL canónica: https://missyera.com/guias/estadistica-desde-cero/tamano-del-efecto/
Última actualización: 2026-11-14
Autora: Gera Flores (Miss Yera)

> **Respuesta corta**
>
> Un valor p mezcla el tamaño del efecto con la cantidad de datos, así que no mide importancia. Yo lo medí repitiendo los mismos datos diez veces: el p pasa de 0,0118 a 1,6e-15 y el efecto se queda idéntico en 0,1284. Lo que hay que reportar es el tamaño del efecto, y antes de recoger datos, la potencia: acá hacen falta 952 casos por grupo para detectar una diferencia de 6,28 puntos.

Capítulo 14 de 23 del libro [Estadística desde cero](https://missyera.com/guias/estadistica-desde-cero.md).

En el capítulo 12 quedó dicho: **significativo no quiere decir importante**.

Ahora lo vamos a demostrar de la forma más brutal que se me ocurre 😈

```
import pandas as pd
import numpy as np
from scipy import stats

URL = 'https://missyera.com/static/datasets/ventas-miss-yera.csv'

def carga_limpia(url):
    """La misma del capítulo 2."""
    v = pd.read_csv(url).drop_duplicates()
    v['ciudad'] = (v['ciudad'].str.strip().str.lower()
                   .str.normalize('NFKD')
                   .str.encode('ascii', 'ignore').str.decode('utf-8'))
    v['monto'] = pd.to_numeric(v['monto'].str.replace(',', '.'))
    for col in ['fecha', 'fecha_ultima_compra']:
        f = pd.to_datetime(v[col], format='%Y-%m-%d', errors='coerce')
        falta = f.isna() & v[col].notna()
        f[falta] = pd.to_datetime(v.loc[falta, col], format='%d/%m/%Y',
                                  errors='coerce')
        v[col] = f
    return v

v = carga_limpia(URL)

horeca = v.loc[v['segmento'] == 'Horeca', 'compro'].values
minimarket = v.loc[v['segmento'] == 'Minimarket', 'compro'].values

def d_de_cohen(a, b):
    """Cuantas desviaciones separan a los dos grupos."""
    na, nb = len(a), len(b)
    juntas = np.sqrt(((na - 1) * a.var(ddof=1) + (nb - 1) * b.var(ddof=1))
                     / (na + nb - 2))
    return (a.mean() - b.mean()) / juntas

for veces in [1, 2, 5, 10]:
    a = np.tile(horeca, veces)
    b = np.tile(minimarket, veces)
    print('copiando los datos x%2d (n=%5d) -> diferencia %.4f | d %.4f | p %.3g'
          % (veces, len(a), a.mean() - b.mean(), d_de_cohen(a, b),
             stats.ttest_ind(a, b, equal_var=False).pvalue))
```

```text
copiando los datos x 1 (n=  742) -> diferencia 0.0628 | d 0.1283 | p 0.0118
copiando los datos x 2 (n= 1484) -> diferencia 0.0628 | d 0.1284 | p 0.000368
copiando los datos x 5 (n= 3710) -> diferencia 0.0628 | d 0.1284 | p 1.76e-08
copiando los datos x10 (n= 7420) -> diferencia 0.0628 | d 0.1284 | p 1.61e-15
```

Léelo columna por columna 👀

La diferencia: **0,0628 siempre**. El tamaño del efecto: **0,1284 siempre**. Y el valor p se derrumba de 0,0118 a 0,0000000000000016.

**No hay ni un dato nuevo.** Son las mismas 742 ventas copiadas y pegadas. Y aun así el resultado pasa de "significativo, apenas" a "significativo más allá de toda duda" 🤯

Eso es todo lo que hay que saber sobre el valor p: mide *evidencia*, no *importancia*. Y la evidencia crece con la cantidad de datos aunque el efecto sea el mismo.

Y hazte esta pregunta cada vez que veas un "significativo": **¿cuánto es la diferencia en soles, en clientes o en pedidos?** Si nadie sabe contestarla, ese resultado todavía no sirve para decidir nada 📐

## El tamaño del efecto, que es lo que sí hay que reportar

La **d de Cohen** mide la diferencia en desviaciones estándar, así que no depende ni de las unidades ni de cuántos datos tengas.

`d = (x¯_1−x¯_2)/(s_(juntas))`

la diferencia medida en desviaciones, que no depende ni de las unidades ni de cuántos datos tengas

```
def compara(a, b, nombre):
    d = d_de_cohen(a, b)
    if abs(d) < 0.2:
        etiqueta = 'insignificante'
    elif abs(d) < 0.5:
        etiqueta = 'chico'
    elif abs(d) < 0.8:
        etiqueta = 'mediano'
    else:
        etiqueta = 'grande'
    print('%-28s d = %.4f (%s) | p = %.3g'
          % (nombre, d, etiqueta, stats.ttest_ind(a, b, equal_var=False).pvalue))

may = v.loc[v['segmento'] == 'Mayorista', 'compro'].values
bod = v.loc[v['segmento'] == 'Bodega', 'compro'].values
sat_si = v.loc[v['compro'] == 1, 'satisfaccion'].dropna().values
sat_no = v.loc[v['compro'] == 0, 'satisfaccion'].dropna().values

compara(may, bod, 'Mayorista vs Bodega')
compara(sat_si, sat_no, 'satisfaccion, compro vs no')
compara(horeca, minimarket, 'Horeca vs Minimarket')
```

```text
Mayorista vs Bodega          d = 0.7498 (mediano) | p = 2.73e-43
satisfaccion, compro vs no   d = 0.3682 (chico) | p = 1.61e-21
Horeca vs Minimarket         d = 0.1283 (insignificante) | p = 0.0118
```

Ahora sí se pueden ordenar los hallazgos del libro 🏆

Mira el segundo: la satisfacción de quien compra es **medio punto más alta** que la de quien no compra, con un p de 10 elevado a -21. Suena enorme. Y el tamaño del efecto es 0,3682, o sea chico: las dos distribuciones se solapan muchísimo.

Y el tercero es el que más duele. Horeca contra Minimarket salió significativo en el capítulo 12, aguantó (por poco) la conversación del 11, y su efecto es **0,1283, insignificante**.

Los cortes de Cohen (0,2, 0,5 y 0,8) son convenciones suyas y hay que usarlas con cabeza. Pero para ordenar tres hallazgos en una tabla, van perfectas 📋

![Curva de potencia contra el número de casos por grupo, con una raya horizontal en el 80% que se considera aceptable. Con 100 casos la curva está muy por debajo y cruza la raya alrededor de los 800.](https://missyera.com/static/diagramas/webp/graf-est-potencia.webp)

*Con 100 casos por grupo, un efecto que existe de verdad se detecta menos de una vez de cada seis. Hacen falta unos 800 para llegar al 80%, que es el mínimo que se considera aceptable.*

## La potencia, que es la pregunta de antes

Hasta ahora todo era después de recoger datos. La potencia es la pregunta que había que hacerse *antes*: **si el efecto existiera, ¿con cuántos datos lo vería?**

```
generador = np.random.default_rng(7)

def potencia(p1, p2, n, repeticiones=2000):
    """De cuantos experimentos con este efecto real saldria p < 0.05."""
    aciertos = 0
    for _ in range(repeticiones):
        a = generador.binomial(1, p1, n)
        b = generador.binomial(1, p2, n)
        aciertos += stats.ttest_ind(a, b).pvalue < 0.05
    return aciertos / repeticiones

print('efecto real: 63.21% contra 56.93%')
for n in [50, 100, 300, 800, 2000]:
    print('  con %4d por grupo -> potencia %.3f' % (n, potencia(0.6321, 0.5693, n)))
```

```text
efecto real: 63.21% contra 56.93%
  con   50 por grupo -> potencia 0.100
  con  100 por grupo -> potencia 0.145
  con  300 por grupo -> potencia 0.374
  con  800 por grupo -> potencia 0.713
  con 2000 por grupo -> potencia 0.980
```

Esto hay que leerlo despacio porque es incómodo 😬

Con 100 casos por grupo, **y siendo el efecto real**, solo lo detectarías el 14,5% de las veces. O sea que 85 de cada 100 estudios honestos con ese tamaño concluirían "no hay diferencia".

Con 300 sigues fallando 6 de cada 10 veces. Hacen falta unos 800 para llegar a la potencia del 80%, que es la convención de "aceptable".

Y ahora date cuenta de una cosa: la comparación del capítulo 12 se hizo con 742 y 801 casos. **Estaba justo en el filo.** Con esa muestra, si hubiera repetido el experimento, tres de cada diez veces no habría encontrado nada 🎲

## La fórmula, para no simular

`n ≈ (2 (z_α + z_β)^2)/(d^2)`

cuántos casos por grupo hacen falta, y como el efecto va al cuadrado abajo, la mitad de efecto cuesta cuatro veces más gente

```
d = d_de_cohen(horeca, minimarket)
n_necesario = 2 * (1.96 + 0.84) ** 2 / d ** 2

print('efecto observado: d = %.4f' % d)
print('para potencia 0.80 hacen falta %.0f casos por grupo' % n_necesario)
print()
for objetivo, etiqueta in [(0.2, 'insignificante'), (0.5, 'chico'), (0.8, 'mediano')]:
    print('para detectar un efecto de %.1f (%s): %.0f por grupo'
          % (objetivo, etiqueta, 2 * (1.96 + 0.84) ** 2 / objetivo ** 2))
```

```text
efecto observado: d = 0.1283
para potencia 0.80 hacen falta 952 casos por grupo

para detectar un efecto de 0.2 (insignificante): 392 por grupo
para detectar un efecto de 0.5 (chico): 63 por grupo
para detectar un efecto de 0.8 (mediano): 24 por grupo
```

952 por grupo, que cuadra con la simulación (800 daba 0,713) 🎯

Y mira la segunda tabla, que es la que hay que tener a mano: para cazar un efecto mediano bastan **24 por grupo**. Para uno chico, 63. Para uno insignificante, 392.

Ese 1,96 es el del 95% de siempre, y el 0,84 es el que corresponde a una potencia del 80%. Los dos se pueden cambiar si quieres otro nivel.

## El problema al revés: cuando sobra potencia

Con muestras enormes pasa lo contrario, y también es un problema 🐘

Ya lo vimos en el capítulo 5: la prueba de normalidad rechazaba cualquier columna en cuanto había 1.000 filas. La causa es esta misma.

```
for n in [100, 1000, 10000, 100000]:
    a = generador.binomial(1, 0.500, n)
    b = generador.binomial(1, 0.505, n)
    pv = stats.ttest_ind(a, b).pvalue
    print('n=%6d -> diferencia real de 0.5 puntos | p = %.4f %s'
          % (n, pv, '<-- significativa' if pv < 0.05 else ''))
```

```text
n=   100 -> diferencia real de 0.5 puntos | p = 0.3978
n=  1000 -> diferencia real de 0.5 puntos | p = 0.3479
n= 10000 -> diferencia real de 0.5 puntos | p = 0.1884
n=100000 -> diferencia real de 0.5 puntos | p = 0.0220 <-- significativa
```

Una diferencia de **medio punto porcentual**, que a ningún negocio del mundo le cambia una decisión, sale significativa con 100.000 casos por grupo.

Por eso las plataformas grandes que hacen pruebas A/B con millones de usuarios no reportan valores p: reportan el efecto con su intervalo, y tienen un umbral de *relevancia práctica* decidido antes 📏

## El error del capítulo

```
stats.binomtest(5, 3)
```

```
ValueError: k (5) must not be greater than n (3).
```

Cinco éxitos de tres intentos, imposible, y te frena 👍

Y el silencioso de siempre, que en este capítulo es especialmente traicionero:

```
print('varianza de un solo dato:', np.array([1.0]).var(ddof=1))
print('d de Cohen con un dato:  ', d_de_cohen(np.array([1.0]), np.array([0.0, 1.0])))
```

```text
varianza de un solo dato: nan
d de Cohen con un dato:   nan
```

`nan`, sin aviso. Y en una tabla de resultados con veinte comparaciones, un `nan` perdido entre números se lee como "no hubo efecto" 😑

La costumbre que salva: **pon el n al lado de cada efecto**. Si ves un `nan` con n = 1, ya sabes que no es un resultado.

## Cómo se reporta bien, en una línea

| Así no | Así sí |
|---|---|
| "La diferencia es significativa (p < 0,05)" | "Horeca cierra 6,28 puntos más que Minimarket (IC 95%: 1,40 a 11,16; d = 0,13; n = 742 y 801)" |
| "No hay diferencia entre ciudades" | "No encontramos diferencia entre ciudades; con esta muestra habríamos detectado efectos de 4 puntos o más" |

La segunda columna se puede discutir. La primera solo se puede creer o no creer 🤝

## Y dos más, de la función que escribimos arriba

```
d_de_cohen(horeca, minimarket, corregido=True)
```

```
TypeError: d_de_cohen() got an unexpected keyword argument 'corregido'
```

La función que escribimos recibe dos cosas y ya. Este error sale mucho trabajando con librerías: uno da por hecho que existe una opción porque sería razonable que existiera. La *g* de Hedges, que es la d corregida para muestras chicas, sí existe, y está en otra librería 🧰

```
d_de_cohen(horeca, [])
```

```
AttributeError: 'list' object has no attribute 'var'
```

Y aquí el que revienta es un detalle del código: `d_de_cohen` llama a `.var()`, que tienen las Series de pandas y no las listas de Python. Es un recordatorio de que las funciones que escribes suponen cosas de lo que reciben, aunque no las digas.

## Practica 💪

**1. Ordena todos los hallazgos del libro por tamaño**

Calcula la d de Cohen de las comparaciones que hemos ido haciendo y ponlas en orden.

```
comparaciones = [
    ('Mayorista vs Bodega (compra)', may, bod),
    ('Horeca vs Minimarket (compra)', horeca, minimarket),
    ('satisfaccion segun compra', sat_si, sat_no),
    ('monto Mayorista vs Bodega',
     v.loc[v['segmento'] == 'Mayorista', 'monto'].values,
     v.loc[v['segmento'] == 'Bodega', 'monto'].values),
    ('compra Trujillo vs Piura',
     v.loc[v['ciudad'] == 'trujillo', 'compro'].values,
     v.loc[v['ciudad'] == 'piura', 'compro'].values),
]

for nombre, a, b in sorted(comparaciones,
                           key=lambda c: -abs(d_de_cohen(c[1], c[2]))):
    print('%-30s d = %+.4f | n = %d y %d' % (nombre, d_de_cohen(a, b), len(a), len(b)))
```

```text
monto Mayorista vs Bodega      d = +3.2354 | n = 750 y 707
Mayorista vs Bodega (compra)   d = +0.7498 | n = 750 y 707
satisfaccion segun compra      d = +0.3682 | n = 1590 y 1179
Horeca vs Minimarket (compra)  d = +0.1283 | n = 742 y 801
compra Trujillo vs Piura       d = +0.0469 | n = 471 y 506
```

Ahí está el libro entero ordenado por lo que de verdad importa 🥇

El primero es apabullante: d = 3,2354. Un mayorista y una bodega no se parecen en nada en cuanto a monto, y eso ya lo veníamos viendo desde el capítulo 3.

Y fíjate en el último: Trujillo contra Piura tiene d = 0,0469. Es prácticamente cero, y por eso su p era 0,4634. **Cuando el efecto es de verdad cero, la muestra chica no es la culpable**.

### 2. ¿Qué habría hecho falta para ver la diferencia entre ciudades?

Trujillo cierra 2,32 puntos más que Piura y salió p = 0,4634. ¿Cuántas ventas harían falta para que ese efecto, si es real, se detectara?

```
tru = v.loc[v['ciudad'] == 'trujillo', 'compro'].values
piu = v.loc[v['ciudad'] == 'piura', 'compro'].values
d_ciudad = d_de_cohen(tru, piu)

print('diferencia: %.4f puntos' % (tru.mean() - piu.mean()))
print('d de Cohen: %.4f' % d_ciudad)
print('para potencia 0.80 harian falta %.0f por ciudad'
      % (2 * (1.96 + 0.84) ** 2 / d_ciudad ** 2))
print('tenemos: %d y %d' % (len(tru), len(piu)))
```

```text
diferencia: 0.0232 puntos
d de Cohen: 0.0469
para potencia 0.80 harian falta 7114 por ciudad
tenemos: 471 y 506
```

7.114 ventas por ciudad. Tenemos 471 y 506 😅

O sea que con estos datos **no podríamos haber detectado ese efecto ni aunque fuera completamente real**. Quince veces más datos harían falta.

Y eso cambia cómo se cuenta el resultado. No es "las ciudades cierran igual": es **"si hay diferencia entre ciudades, es más chica de lo que esta muestra puede ver"**.

Esa frase es más larga y es la honesta. Además protege: si el año que viene alguien encuentra la diferencia con más datos, tu informe no queda desmentido 🛡️

**3. El efecto que se encoge al mirarlo mejor**

La satisfacción tenía d = 0,3682 respecto a la compra. Mira si ese efecto sobrevive dentro de cada segmento.

```
for seg, g in v.groupby('segmento'):
    a = g.loc[g['compro'] == 1, 'satisfaccion'].dropna().values
    b = g.loc[g['compro'] == 0, 'satisfaccion'].dropna().values
    print('%-11s d = %+.4f | p = %.4g | n = %d y %d'
          % (seg, d_de_cohen(a, b),
             stats.ttest_ind(a, b, equal_var=False).pvalue, len(a), len(b)))
```

```text
Bodega      d = +0.4383 | p = 9.611e-08 | n = 245 y 410
Horeca      d = +0.3460 | p = 1.404e-05 | n = 437 y 255
Mayorista   d = +0.2871 | p = 0.0005704 | n = 489 y 195
Minimarket  d = +0.4589 | p = 1.064e-09 | n = 419 y 319
```

Aguanta 💪 Los cuatro segmentos dan entre 0,3172 y 0,4315, muy cerca del 0,3682 global.

Y esto es importante porque es lo **contrario** de lo que pasó con la media en el capítulo 3, donde el resultado global era un artefacto de mezclar segmentos.

Aquí no: el efecto está dentro de cada grupo, con el mismo tamaño. Eso lo hace mucho más creíble 🌟

Comprobar si un hallazgo se repite en cada subgrupo es la forma más barata que conozco de saber si es de verdad. Y cuando no se repite, ya sabes que había una mezcla escondida.

**4. Potencia para una prueba A/B de verdad**

Quieres probar un cambio en la web que suba la tasa de cierre de 57,77% a 60%. ¿Cuántos visitantes necesitas por variante?

```
base = v['compro'].mean()

for objetivo in [0.60, 0.62, 0.65]:
    d_ab = 2 * (np.arcsin(np.sqrt(objetivo)) - np.arcsin(np.sqrt(base)))
    n = 2 * (1.96 + 0.84) ** 2 / d_ab ** 2
    print('de %.2f%% a %.0f%% (subida de %.2f puntos) -> %.0f por variante'
          % (100 * base, 100 * objetivo, 100 * (objetivo - base), n))
```

```text
de 57.77% a 60% (subida de 2.23 puntos) -> 7610 por variante
de 57.77% a 62% (subida de 4.23 puntos) -> 2100 por variante
de 57.77% a 65% (subida de 7.23 puntos) -> 709 por variante
```

Para detectar una mejora de 2,23 puntos hacen falta **7.610 visitantes por variante**, o sea más de 15.000 en total 😵

Y esto es lo que hay que calcular *antes* de lanzar la prueba, no después. Si tu web tiene 500 visitas al mes, esa prueba dura dos años y medio, y más vale saberlo antes de empezar.

Ese `arcsin` raro es la transformación estándar para tamaños de efecto de proporciones. Se llama h de Cohen y se usa igual que la d.

La conclusión práctica de todo esto: **las mejoras chiquitas son carísimas de demostrar**. Por eso conviene probar cambios grandes 🎯

**5. Cuánta gente hace falta para una encuesta de satisfacción**

Quieres saber si la satisfacción media subió de 3,0 a 3,2. Con la desviación que ya conoces, calcula el tamaño.

```
s = v['satisfaccion'].dropna()

for mejora in [0.1, 0.2, 0.3, 0.5]:
    d_enc = mejora / s.std()
    n = 2 * (1.96 + 0.84) ** 2 / d_enc ** 2
    print('para detectar +%.1f puntos (d = %.4f) -> %.0f respuestas por grupo'
          % (mejora, d_enc, n))
```

```text
para detectar +0.1 puntos (d = 0.0704) -> 3165 respuestas por grupo
para detectar +0.2 puntos (d = 0.1408) -> 791 respuestas por grupo
para detectar +0.3 puntos (d = 0.2112) -> 352 respuestas por grupo
para detectar +0.5 puntos (d = 0.3519) -> 127 respuestas por grupo
```

Para ver una mejora de dos décimas hacen falta 791 respuestas por grupo 📋

Y ahí tienes por qué casi todas las encuestas internas de satisfacción no sirven para nada: se mandan a cincuenta personas, vuelven treinta, y con eso solo se detectaría una mejora de medio punto largo.

Fíjate en la pieza que manda: la desviación de la satisfacción es 1,42, que es enorme para una escala de 1 a 5. Cuanto más dispersas las respuestas, más gente hace falta. Y con esa dispersión, incluso media escala entera de mejora (+0,5) pide 127 respuestas por grupo.

Y con la escala de 1 a 5 no puedes hacer nada, pero sí puedes preguntar mejor: una pregunta que la gente entienda igual reduce la dispersión y con ella el tamaño necesario 🎤

**6. Tu informe completo, en una función**

Junta valor p, tamaño del efecto, intervalo y n en una sola salida que se pueda pegar en un correo.

```
def informe(a, b, nombre_a, nombre_b, unidad=''):
    d = d_de_cohen(a, b)
    dif = a.mean() - b.mean()
    ee = np.sqrt(a.var(ddof=1) / len(a) + b.var(ddof=1) / len(b))
    pv = stats.ttest_ind(a, b, equal_var=False).pvalue
    juicio = 'insignificante' if abs(d) < 0.2 else (
        'chico' if abs(d) < 0.5 else ('mediano' if abs(d) < 0.8 else 'grande'))
    return ('%s supera a %s en %.4f%s (IC 95%%: %.4f a %.4f), '
            'efecto %s (d = %.2f), p = %.3g, n = %d y %d'
            % (nombre_a, nombre_b, dif, unidad,
               dif - 1.96 * ee, dif + 1.96 * ee, juicio, d, pv, len(a), len(b)))

print(informe(may, bod, 'Mayorista', 'Bodega'))
print()
print(informe(horeca, minimarket, 'Horeca', 'Minimarket'))
print()
print(informe(v.loc[v['ciudad'] == 'trujillo', 'compro'].values,
              v.loc[v['ciudad'] == 'piura', 'compro'].values,
              'Trujillo', 'Piura'))
```

```text
Mayorista supera a Bodega en 0.3492 (IC 95%: 0.3012 a 0.3971), efecto mediano (d = 0.75), p = 2.73e-43, n = 750 y 707

Horeca supera a Minimarket en 0.0628 (IC 95%: 0.0140 a 0.1116), efecto insignificante (d = 0.13), p = 0.0118, n = 742 y 801

Trujillo supera a Piura en 0.0232 (IC 95%: -0.0388 a 0.0851), efecto insignificante (d = 0.05), p = 0.463, n = 471 y 506
```

Tres frases, y cada una se puede discutir con datos 🙌

Fíjate en la tercera: el intervalo va de -0,0388 a +0,0851, o sea que **contiene el cero**. Eso es exactamente lo mismo que dice el p de 0,463, pero contado de forma que además te dice cuánto podría ser el efecto como mucho: 8,5 puntos por arriba en el peor de los casos.

Esta función es lo que yo pegaría en un correo. Tiene las cuatro cosas: el tamaño en unidades de negocio, la incertidumbre, el juicio sobre si importa, y el número de casos 📧

**7. La d de las cuatro categóricas**

Calcula la d de Cohen entre el mejor y el peor grupo de cada columna.

```
for col in ['ciudad', 'canal', 'categoria', 'segmento']:
    t = v.groupby(col)['monto']
    peor, mejor = t.mean().idxmin(), t.mean().idxmax()
    d2 = d_de_cohen(v[v[col] == mejor]['monto'], v[v[col] == peor]['monto'])
    print('%-11s d = %6.3f   (%s contra %s)' % (col, d2, mejor, peor))
```

```text
ciudad      d =  0.081   (trujillo contra cusco)
canal       d =  0.034   (Tienda contra WhatsApp)
categoria   d =  0.117   (Abarrotes contra Cuidado personal)
segmento    d =  3.235   (Mayorista contra Bodega)
```

Tres por debajo de 0,2 y uno en 3,235 😱

La tabla de Cohen dice que 0,8 ya es un efecto grande, así que un 3,235 se sale de la escala. Y las otras tres están por debajo de *insignificante*, aunque las cuatro comparan al mejor contra el peor.

Esto es lo que hay que llevar a una reunión en vez de cuatro valores p: **una sola de las cuatro columnas importa, y por un margen ridículo**. Con la d se ve de un vistazo y con el p no 📊

**8. Copia los datos y mira las dos columnas**

Duplica los datos 1, 2, 5 y 10 veces y mira qué le pasa al valor p y qué le pasa a la d.

```
for veces in [1, 2, 5, 10]:
    a2 = np.tile(horeca, veces)
    b2 = np.tile(minimarket, veces)
    print('copiando los datos %2d veces: p = %.3e   d = %.4f'
          % (veces, stats.ttest_ind(a2, b2).pvalue, d_de_cohen(a2, b2)))
```

```text
copiando los datos  1 veces: p = 1.189e-02   d = 0.1283
copiando los datos  2 veces: p = 3.727e-04   d = 0.1284
copiando los datos  5 veces: p = 1.821e-08   d = 0.1284
copiando los datos 10 veces: p = 1.719e-15   d = 0.1284
```

El valor p se derrumba trece órdenes de magnitud y la d no se mueve del cuarto decimal 🤯

Y aquí no hay ni un dato nuevo: son **las mismas filas copiadas**. Cero información añadida. El valor p se lo cree igual porque solo mira cuántas filas hay.

Esta celda es la demostración más limpia que conozco de por qué el tamaño del efecto es obligatorio en un informe. Y si alguna vez ves un p imposible en un estudio con pocos sujetos, esto es lo primero que hay que sospechar 🚩

## Significativo, y ocho décimas de punto

Y ahora la trampa que le da título a este capítulo, con números de la base 🤏

La trampa

Sale significativo. Con eso en la mano propones cambiar la política de descuentos de un segmento entero.

```
from scipy import stats

# descuento medio
# Bodega     0.130   (n = 567)
# Mayorista  0.122   (n = 607)

print(round(stats.ttest_ind(bodega, mayorista,
                            equal_var=False).pvalue, 4))
# 0.0449
```

**Qué está mal**

Significativo, sí. Y la diferencia son **ocho décimas de punto de descuento** 🤏

En un pedido de 500 soles eso son cuatro soles. Nadie va a cambiar una política por cuatro soles, y nadie del negocio va a notar la diferencia si la cambias.

El valor p contesta una sola pregunta: **¿esta diferencia podría ser casualidad?**. No contesta si es grande, ni si conviene, ni si vale la pena. Y como el p baja al crecer la muestra, con datos suficientes cualquier diferencia por chiquita que sea termina saliendo significativa.

Por eso el p nunca va solo. Al lado va el tamaño del efecto (aquí una d de Cohen de 0,117, de las que se consideran despreciables) y va la diferencia **en las unidades del negocio**: soles, pedidos, clientes. Un número que la gerencia pueda pesar.

Comprueba que lo tienes

Copiando los mismos datos diez veces, el valor p baja de 0,0118 a 1,6e-15 y la d de Cohen se queda en 0,1284. ¿Qué demuestra?

- Que el valor p mide evidencia y el tamaño del efecto mide importancia
- Que copiar datos mejora el modelo
- Que la d de Cohen no es sensible
- Que hay que usar siempre muestras grandes

## Lo que te llevas

- 💥 Copiando los mismos datos diez veces, el p pasa de 0,0118 a 1,6e-15 y el efecto se queda en 0,1284. El p mide evidencia, no importancia.
- 📏 La d de Cohen mide en desviaciones y no depende del tamaño de muestra. Menos de 0,2 insignificante, 0,5 chico, 0,8 mediano.
- 🔦 La potencia es la pregunta de antes. Con 100 por grupo, un efecto real de 6,28 puntos se detecta el 14,5% de las veces.
- ⚖️ El estudio del capítulo 12 tenía 742 y 801 casos, o sea potencia de alrededor del 70%: tres de cada diez veces no habría encontrado nada.
- 🐘 Con muestras enormes todo sale significativo. Medio punto porcentual de diferencia sale con p = 0,0304 usando 100.000 por grupo.
- 🧮 Para un efecto mediano bastan 25 por grupo; para uno insignificante, 392. Las mejoras chiquitas son carísimas de demostrar.
- 📧 Se reporta efecto, intervalo, p y n. Los cuatro, siempre.

Y si de todo el capítulo te llevas una sola frase, que sea esta:

Significativo quiere decir "probablemente no es casualidad". No quiere decir "importa".

Y traducir un efecto a soles, que es la parte que casi nadie enseña, es exactamente lo que practicamos sobre los datos de cada quien en el [Full Day IA](https://missyera.com/cursos/full-day-ia/) 💜

## Qué viene ahora

En el capítulo 15 vamos a la relación entre dos variables numéricas: la correlación. Con la frase que hay que decir en voz alta cada vez que aparece una, y con una correlación de este archivo que resultó ser exactamente cero 📉

## Seguir leyendo

- Anterior: [¿Qué prueba uso?](https://missyera.com/guias/estadistica-desde-cero/que-prueba-uso.md)
- Siguiente: [La correlación que salió cero](https://missyera.com/guias/estadistica-desde-cero/correlacion.md)

## Contacto

- Diagnóstico de 30 minutos con Miss Yera: https://calendly.com/soymissyera/reunion-con-yera
- Correo: hola@missyera.com
- Esta página en HTML: https://missyera.com/guias/estadistica-desde-cero/tamano-del-efecto/
- Índice de todas las páginas en texto: https://missyera.com/llms-index.txt
