Skip to content
Snippets Groups Projects
Commit c0ccbb63 authored by Camila Rangel Smith's avatar Camila Rangel Smith
Browse files

Update pruebas_de_hipotesis.ipynb

parent 4b296ee1
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
# Pruebas de hipótesis
%% Cell type:markdown id: tags:
Este notebook esta basado en el materia de [este repositorio](https://github.com/ethen8181/machine-learning/blob/master/ab_tests/frequentist_ab_test.ipynb) y ha sido traducido y adaptado para esta práctica.
%% Cell type:code id: tags:
``` python
import numpy as np
import pandas as pd
import seaborn as sns
import scipy.stats as stats
import matplotlib.pyplot as plt
from statsmodels.stats.proportion import proportions_ztest
from statsmodels.stats.proportion import proportions_chisquare
```
%% Cell type:code id: tags:
``` python
# configurar el aspecto del notebook
plt.rcParams['figure.figsize'] = 8, 6
sns.set_context('notebook', font_scale = 1.5, rc = {'lines.linewidth': 2.5})
sns.set_style('whitegrid')
sns.set_palette('deep')
# Crear un par de colores para usar en todo el notebook
red = sns.xkcd_rgb['vermillion']
blue = sns.xkcd_rgb['dark sky blue']
```
%% Cell type:markdown id: tags:
La inferencia estadística es el proceso de análisis de muestras de datos para obtener información sobre la población de la que se recogieron los datos y para investigar las diferencias entre las muestras de datos.
En el análisis de datos, a menudo nos interesan las características de una población grande, pero la recolección de datos de toda la población puede ser imposible. Por ejemplo, en vísperas de las elecciones presidenciales de EE.UU. podría ser muy útil conocer las inclinaciones políticas de cada uno de los votantes con derecho a voto, pero encuestar a todos los votantes no es factible.
En su lugar, podríamos encuestar a un subconjunto de la población, como mil votantes registrados, y utilizar esos datos para hacer inferencias sobre el conjunto de la población.
%% Cell type:markdown id: tags:
## Point estimates (estimación puntual de un parametro)
%% Cell type:markdown id: tags:
Las estimaciones puntuales son estimaciones de los parámetros de la población basadas en datos de la muestra. Por ejemplo, si quisiéramos saber la edad media de los votantes registrados en EE.UU., podríamos realizar una encuesta entre los votantes registrados y utilizar la edad media de los encuestados como una estimación puntual de la edad media de la población en su conjunto.
La media de la muestra no suele ser exactamente igual a la media de la población. Esta diferencia puede deberse a muchos factores, como un diseño deficiente de la encuesta, métodos de muestreo sesgados y la aleatoriedad inherente a la extracción de una muestra de una población. Investiguemos las estimaciones puntuales generando una población de datos de edad aleatorios y extrayendo luego una muestra de ella para estimar la media:
%% Cell type:code id: tags:
``` python
# generar algún número aleatorio que nos sirva de población
np.random.seed(10)
poblacion_edad1 = stats.poisson.rvs(loc = 18, mu = 35, size = 150000)
poblacion_edad2 = stats.poisson.rvs(loc = 18, mu = 10, size = 100000)
poblacion_edad = np.concatenate((poblacion_edad1, poblacion_edad2))
print('media de la población:', np.mean(poblacion_edad))
```
%% Output
media de la población: 43.002372
%% Cell type:code id: tags:
``` python
np.random.seed(6)
muestra_edad = np.random.choice(poblacion_edad, size = 500)
print('media de la muestra:', np.mean(muestra_edad))
```
%% Output
media de la muestra: 42.388
%% Cell type:markdown id: tags:
El experimento nos dice que es de esperar que la distribución de la población tenga una forma similar a la de la muestra, por lo que podemos suponer que la media de la muestra y de la población deberían tener el mismo valor. Hay que tener en cuenta que no podemos decir que coincidan exactamente, pero es la mejor estimación que podemos hacer.
La media de la población se suele denotar como $\mu$, la media estimada de la población como $\hat{\mu}$, la media de la muestra $\bar{x}$. Así que aquí estamos diciendo básicamente $\hat{\mu} = \bar{x}$, donde estamos utilizando la media de la muestra para estimar la media de la población y, por lo general, cuanto mayor sea el tamaño de nuestra muestra, más preciso será nuestro estimador puntual para la media poblacional estimada.
%% Cell type:markdown id: tags:
## Distribuciones de muestreo y el teorema del límite central
%% Cell type:markdown id: tags:
Muchos procedimientos estadísticos asumen que los datos siguen una distribución normal, porque la distribución normal tiene buenas propiedades como ser simétrica y tener la mayoría de los datos agrupados dentro de unas pocas desviaciones estándar de la media. Por desgracia, los datos del mundo real no suelen tener una distribución normal y la distribución de una muestra tiende a reflejar la distribución de la población. Esto significa que una muestra tomada de una población con una distribución sesgada también tenderá a ser sesgada.
%% Cell type:code id: tags:
``` python
fig = plt.figure(figsize = (12, 6))
plt.subplot(1, 2, 1)
plt.hist(poblacion_edad)
plt.title('Población')
plt.subplot(1, 2, 2)
plt.hist(muestra_edad)
plt.title('Muestra')
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
El gráfico revela que los datos no son claramente normales: en lugar de una curva de campana simétrica, tienen una distribución bimodal con dos picos de alta densidad. Por ello, la muestra que extrajimos de esta población debería tener aproximadamente la misma forma y asimetría.
La muestra tiene aproximadamente la misma forma que la población subyacente. Esto sugiere que no podemos aplicar técnicas que asumen una distribución normal a este conjunto de datos, ya que no es normal. Esto nos lleva a nuestro siguiente tema, el teorema del límite central.
El teorema del límite central es uno de los resultados más importantes de la teoría de la probabilidad y sirve de base a muchos métodos de análisis estadístico. A alto nivel, el teorema afirma que la distribución de muchas medias muestrales, conocida como distribución muestral, se distribuirá normalmente. Esta regla es válida incluso si la propia distribución subyacente no está distribuida normalmente. En consecuencia, podemos tratar la media muestral como si se dibujara una distribución normal. Para ilustrarlo, creemos una distribución de muestreo tomando 200 muestras de nuestra población y haciendo luego 200 estimaciones puntuales de la media:
%% Cell type:code id: tags:
``` python
np.random.seed(10)
samples = 200
point_estimates = [np.random.choice(poblacion_edad, size = 500).mean()
for _ in range(samples)]
plt.hist(point_estimates)
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
La distribución del muestreo parece ser aproximadamente normal, a pesar de la distribución bimodal de la población de la que se extrajeron las muestras. Además, la media de la distribución muestral se aproxima a la media real de la población:
%% Cell type:code id: tags:
``` python
poblacion_edad.mean() - np.mean(point_estimates)
```
%% Output
-0.08440799999999626
%% Cell type:markdown id: tags:
Para que quede claro, el Teorema del Límite Central afirma que si recogemos "un gran número" de muestras diferentes de la media de la población, la distribución del muestreo, la distribución de la media de las muestras recogidas, adoptará aproximadamente la forma de una distribución normal en torno a la media de la población, independientemente de cuál sea la distribución original de la población.
Saber que la distribución muestral adoptará la forma de una distribución normal es lo que hace que el teorema sea tan poderoso, ya que es el fundamento de conceptos como los intervalos de confianza y los márgenes de error en la estadística frecuentista.
%% Cell type:markdown id: tags:
## Intervalos de confianza
%% Cell type:markdown id: tags:
Una estimación puntual puede darnos una idea aproximada de un parámetro poblacional como la media, pero las estimaciones son propensas a errores. Un intervalo de confianza es un rango de valores por encima y por debajo de una estimación puntual que capta el verdadero parámetro de la población con un nivel de confianza predeterminado. Por ejemplo, si quiere tener un 95% de posibilidades de capturar el verdadero parámetro de la población con una estimación puntual y un intervalo de confianza correspondiente, estableceríamos nuestro nivel de confianza en el 95%. Los niveles de confianza más altos dan lugar a intervalos de confianza más amplios.
El intervalo se calcula mediante la fórmula
$$
\begin{align}
\text{parametro estimado} \pm z * SE
\end{align}
$$
Donde
- $z$ se llama valor crítico y corresponde al nivel de confianza que hemos elegido. El valor crítico es el número de desviaciones estándar que tendríamos que alejar de la media de la distribución normal para capturar la proporción de los datos asociada al nivel de confianza deseado. Por ejemplo, sabemos que aproximadamente el 95% de los datos de una distribución normal se encuentra dentro de 2 desviaciones estándar de la media, por lo que podríamos utilizar 2 como valor crítico z para un intervalo de confianza del 95% (aunque es más exacto obtener valores críticos z con `stats.norm.ppf()`)
- $SE$ representa el error estándar. Por lo general, el error estándar de una estimación puntual se estima a partir de los datos y se calcula mediante una fórmula. Por ejemplo, el error estándar para la media muestral $\frac{s}{ \sqrt{n} }$, donde $s$ es la desviación estándar y n es el número de muestras.
- El valor $z * SE$ se denomina margen de error. Observe que este marco de construcción de intervalos de confianza puede adaptarse fácilmente para cualquier estimador que tenga una distribución muestral casi normal. por ejemplo, la media muestral, la media de dos muestras, la proporción muestral y la proporción de dos muestras (lo veremos más adelante). Todo lo que tenemos que hacer es cambiar la forma de calcular el error estándar.
%% Cell type:code id: tags:
``` python
np.random.seed(10)
tamano_muestra = 1000
muestra = np.random.choice(poblacion_edad, size = tamano_muestra)
media_muestra = muestra.mean()
intervalo_confianza = 0.95
z_critico = stats.norm.ppf(q = intervalo_confianza + (1 - intervalo_confianza) / 2)
print('valor z crítico:', z_critico)
poblacion_stdev = poblacion_edad.std()
margen_error = z_critico * (poblacion_stdev / np.sqrt(tamano_muestra))
int_conf = media_muestra - margen_error, media_muestra + margen_error
print('parámetro estimado:', media_muestra)
print('Intervalo de confianza:', int_conf)
```
%% Output
valor z crítico: 1.959963984540054
parámetro estimado: 42.523
Intervalo de confianza: (41.70306406882683, 43.34293593117317)
%% Cell type:markdown id: tags:
Observa que el intervalo de confianza que hemos calculado captura la verdadera media de la población de 43,0023. Vamos a crear varios intervalos de confianza y a trazarlos para tener una mejor idea de lo que significa "capturar" la verdadera media:
%% Cell type:code id: tags:
``` python
np.random.seed(12)
intervalo_confianza = 0.95
tamano_muestra = 1000
intervalos = []
muestras = []
for sample in range(25):
muestra = np.random.choice(poblacion_edad, size = tamano_muestra)
media_muestra = muestra.mean()
muestras.append(media_muestra)
z_critico = stats.norm.ppf(q = intervalo_confianza + (1 - intervalo_confianza) / 2)
poblacion_stdev = poblacion_edad.std()
margen_error = z_critico * (poblacion_stdev / np.sqrt(tamano_muestra))
int_conf = media_muestra - margen_error, media_muestra + margen_error
intervalos.append(int_conf)
plt.figure(figsize = (10, 8))
plt.errorbar(x = np.arange(0.1, 25, 1), y = muestras,
yerr = [(top - bot) / 2 for top, bot in intervalos], fmt = 'o')
plt.hlines(xmin = 0, xmax = 25,
y = poblacion_edad.mean(),
linewidth = 2.0, color = red)
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
Observe que en el gráfico anterior, todos los intervalos de confianza del 95%, excepto uno, se superponen a la línea roja que marca la media real. Esto es de esperar: dado que un intervalo de confianza del 95% capta la media real el 95% de las veces, es de esperar que nuestro intervalo no capte la media real el 5% de las veces.
Más formalmente, la definición de un intervalo de confianza del 95% significa que el 95% de los intervalos de confianza, creados a partir de muestras aleatorias del mismo tamaño de la misma población, contendrán el verdadero parámetro poblacional.
%% Cell type:markdown id: tags:
## Prueba de hipótesis
%% Cell type:markdown id: tags:
Empecemos con un experimento que plantea la pregunta "Si lanzas una moneda 30 veces y ves 22 caras, ¿es una moneda justa?"
Todos sabemos que una moneda justa debería salir cara aproximadamente 15 de cada 30 lanzamientos, más o menos, así que parece poco probable ver tantas caras. Sin embargo, los escépticos podrían argumentar que incluso una moneda justa podría dar 22 caras en 30 lanzamientos de vez en cuando. Podría tratarse de una casualidad. Entonces, la pregunta sería "¿cómo se puede determinar si estamos lanzando una moneda justa?".
Empecemos por considerar primero la probabilidad de que una sola moneda salga cara y sigamos hasta 22 de 30.
$$
\begin{align}
P(H) = \frac{1}{2}
\end{align}
$$
Como muestra nuestra ecuación, la probabilidad de que una sola moneda salga cara es exactamente el 50%, ya que hay la misma posibilidad de que salga cara o cruz. Dando un paso más, para determinar la probabilidad de obtener 2 cabezas seguidas con 2 lanzamientos de moneda, tendríamos que multiplicar la probabilidad de obtener cabezas por la probabilidad de obtener cabezas de nuevo, ya que los dos eventos son independientes el uno del otro.
$$
\begin{align}
P(HH) = P(H) \cdot P(H) = P(H)^2 = \left(\frac{1}{2}\right)^2 = \frac{1}{4}
\end{align}
$$
Veamos ahora un escenario ligeramente diferente y calculemos la probabilidad de obtener 2 caras y 1 cruz con 3 lanzamientos de moneda. Para obtener la probabilidad real de sacar 2 caras y 1 cruz tendremos que sumar las probabilidades de todas las permutaciones posibles, de las cuales hay exactamente tres: HHT, HTH y THH.
$$
\begin{align}
P(2H,1T) = P(HHT) + P(HTH) + P(THH) = \frac{1}{8} + \frac{1}{8} + \frac{1}{8} = \frac{3}{8}
\end{align}
$$
Otra forma de hacerlo es utilizar la distribución binomial:
$$
\begin{align}
P(N_H,N_T) = \binom{n}{k} p^{k} \left( 1 - p \right)^{n - k}
\end{align}
$$
Dónde
- $n$ es el número de lanzamientos de la moneda
- $p$ es la probabilidad de obtener caras en cada tirada
El $\binom{n}{k}$ nos dice cuántas formas hay de obtener $k$ caras de un número total de $n$ lanzamientos de la moneda" y el $p^k(1-p)^{n-k}$ responde a la pregunta "¿cuál es la probabilidad de obtener $k$ caras y $n-k$ cruz?", multiplíquelos y obtendremos la probabilidad de obtener exactamente $k$ caras.
Ahora que entendemos el método clásico, vamos a utilizarlo para comprobar si realmente estamos lanzando una moneda justa.
%% Cell type:code id: tags:
``` python
# Calcular la probabilidad para cada resultado posible
# de lanzar una moneda justa 30 k_range
k_rango = range(1, 31) # rango del número de cabezas que aparecen
n = 30 # número de k_range lanzando la moneda
p = 0.5 # probabilidad de que la moneda salga cara
prob = stats.binom(n = n, p = p).pmf(k = k_rango)
# Plot the probability distribution using the probabilities list
# we created above.
plt.step(k_rango, prob, where = 'mid', color = blue)
plt.xlabel('Número de caras')
plt.ylabel('Probabilidad')
plt.plot((22, 22), (0, 0.1599), color = red)
plt.annotate('0.8%', xytext = (25, 0.08), xy = (22, 0.08),
va = 'center', color = red, size = 'large',
arrowprops = {'arrowstyle': '<|-', 'lw': 2,
'color': red, 'shrinkA': 10})
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
La visualización anterior muestra la distribución de la probabilidad de lanzar una moneda justa 30 veces. Utilizando esta visualización podemos determinar la probabilidad de obtener, por ejemplo, 12 caras en 30 lanzamientos, que parece ser de aproximadamente el 8%. Fíjate en que hemos etiquetado nuestro ejemplo de 22 caras como 0,8%. Si miramos la probabilidad de sacar exactamente 22 caras, parece ser un poco menos del 0,8%, de hecho si la calculamos usando la función de arriba, obtenemos el 0,5%.
%% Cell type:code id: tags:
``` python
prob = stats.binom(n = n, p = p).pmf(k = 22)
print('Probabilidad de sacar 22 caras: {:0.1f}%'.format(prob * 100))
```
%% Output
Probabilidad de sacar 22 caras: 0.5%
%% Cell type:markdown id: tags:
Entonces, ¿por qué tenemos etiquetado el 0,8% en nuestra distribución de probabilidad anterior? Bueno, eso es porque estamos mostrando la probabilidad de obtener al menos 22 cabezas, que también se conoce como el **p-value**.
Volvamos a nuestro ejemplo y discutamos formalmente sobre las pruebas de hipótesis. En las pruebas de hipótesis de la estadística frecuentista estándar, empezamos con una hipótesis nula que solemos llamar H0, que representa nuestro statu quo. Por otro lado, también tenemos una hipótesis alternativa, nuestra H1, que representa la pregunta que queremos responder, es decir, lo que estamos probando.
Después de establecer nuestra hipótesis nula y alternativa, realizamos una prueba de hipótesis bajo el supuesto de que la hipótesis nula es verdadera. Si los resultados de la prueba sugieren que los datos no aportan pruebas convincentes para la hipótesis alternativa, nos quedamos con la hipótesis nula. Si lo hacen, rechazamos la hipótesis nula a favor de la alternativa.
La prueba de hipótesis de los estadísticos frecuentistas utiliza un valor p para sopesar la fuerza de la evidencia (lo que los datos dicen sobre la población). El valor p se define como la probabilidad de obtener el resultado observado o más extremo, dado que la hipótesis nula es verdadera (no la probabilidad de que la hipótesis alternativa sea verdadera). Es un número entre 0 y 1 y se interpreta de la siguiente manera:
- Un p-value pequeño (normalmente <= 0,05, 0,05 es un umbral comúnmente utilizado, el umbral se denota a menudo como $\alpha$) indica una fuerte evidencia contra la hipótesis nula, por lo que rechazamos la hipótesis nula. Esto significa que está ocurriendo algo interesante y que no es sólo ruido.
- Un p-value (> 0,05) indica una evidencia débil contra la hipótesis nula, por lo que no rechazamos la hipótesis nula. Aunque el valor p sigue estando a nuestro favor, no podemos afirmar de forma concluyente que no se deba al ruido aleatorio.
- Los valores p muy cercanos al límite (0,05) se consideran marginales (podrían ir en cualquier dirección). Si se leen con atención los buenos artículos sobre este tipo de temas, siempre se informará de los valores p para que los lectores puedan sacar sus propias conclusiones.
**Ejemplo**:
Supongamos que una pizzería afirma que sus tiempos de entrega son de 30 minutos o menos de media. Ahora creemos que en realidad tarda más de 30 minutos. Realizamos una prueba de hipótesis porque creemos que la hipótesis nula, que el tiempo medio de entrega es de 30 minutos como máximo, es incorrecta. Esto significa que nuestra hipótesis alternativa es que el tiempo medio es superior a 30 minutos. Tomamos una muestra aleatoria de algunos tiempos de entrega y sometemos los datos a la prueba de hipótesis, y nuestro valor p resulta ser 0,01, que es mucho menos que 0,05.
En términos reales, hay una probabilidad de 0,01 de que rechacemos erróneamente la afirmación de la pizzería de que su tiempo de entrega es inferior o igual a 30 minutos. Dado que normalmente estamos dispuestos a rechazar la hipótesis nula cuando esta probabilidad es inferior a 0,05, concluimos que la pizzería está equivocada; sus tiempos de entrega son, de hecho, superiores a 30 minutos de media.
%% Cell type:markdown id: tags:
Volviendo a nuestro ejemplo del lanzamiento de la moneda, la hipótesis nula supone que tenemos una moneda justa, y la forma de determinar si esta hipótesis es cierta o no es calculando la frecuencia con la que el lanzamiento de esta moneda justa 30 veces daría como resultado 22 o más caras. Si entonces tomamos el número de veces que obtuvimos 22 o más caras y dividimos ese número por el total de todas las permutaciones posibles de 30 lanzamientos de la moneda, obtenemos la probabilidad de lanzar 22 o más caras con una moneda justa. Esta probabilidad es esencialmente nuestro **p-value**.
%% Cell type:code id: tags:
``` python
def calcular_pvalue(n, k, p):
"""Devuelve el valor p para la distribución binomial"""
k_rango = range(k, n + 1)
pvalue = stats.binom(n = n, p = p).pmf(k = k_rango).sum()
return pvalue
pvalue = calcular_pvalue(n = 30, k = 22, p = 0.5)
print('P-value: {:0.1f}%'.format(pvalue * 100))
```
%% Output
P-value: 0.8%
%% Cell type:markdown id: tags:
El papel del **p-value** se utiliza para comprobar la validez de la hipótesis nula. La forma de hacerlo es acordando un límite superior predeterminado para nuestro valor p, por debajo del cual asumiremos que nuestra hipótesis nula es falsa.
En otras palabras, si nuestra hipótesis nula fuera cierta, y 22 caras en 30 lanzamientos pudieran ocurrir con suficiente frecuencia por azar, esperaríamos que ocurriera más veces que el porcentaje de umbral dado. Así, por ejemplo, si elegimos el 10% como umbral del valor p, entonces esperaríamos ver que 22 o más caras aparecen al menos el 10% de las veces para determinar que se trata de un suceso fortuito y no debido a algún sesgo en la moneda. Históricamente, el umbral generalmente aceptado ha sido el 5%, por lo que si nuestro valor p es inferior al 5%, podemos suponer que nuestra moneda puede no ser justa.
La ejecución del código anterior nos da un valor p de aproximadamente 0,8%, que coincide con el valor de nuestra distribución de probabilidad anterior y también es inferior al umbral del 5% necesario para rechazar nuestra hipótesis nula, por lo que parece que podemos tener una moneda sesgada.
%% Cell type:code id: tags:
``` python
# también podemos utilizar la función binom_test de scipy para
# realizar la prueba de hipótesis
pvalue = stats.binom_test(x = 22, n = 30, p = 0.5, alternative = 'greater')
print('P-value: {:0.1f}%'.format(pvalue * 100))
```
%% Output
P-value: 0.8%
%% Cell type:markdown id: tags:
## Simulación o toys
%% Cell type:markdown id: tags:
En lugar de utilizar el enfoque estadístico, el código siguiente trata de responder a la misma pregunta de si nuestra moneda es justa o no, ejecutando un gran número de lanzamientos de moneda simulados y calculando la proporción de estos experimentos que dieron como resultado al menos 22 caras o más.
%% Cell type:code id: tags:
``` python
def lanzamiento_moneda(n_toys = 100000):
"""
calcular una moneda justa que dé como resultado al menos
al menos 22 caras o más a través de la simulación
"""
pvalue = 0
for i in range(n_toys):
# ensayos: 1 significa cara, 0 significa cruz
ensayos = np.random.randint(2, size = 30)
if ensayos.sum() >= 22:
pvalue += 1
pvalue /= n_toys
return pvalue
pvalue = lanzamiento_moneda()
print('Simulated P-value: {:0.1f}%'.format(pvalue * 100))
```
%% Output
Simulated P-value: 0.8%
%% Cell type:markdown id: tags:
El resultado de nuestras simulaciones es del 0,8%, exactamente el mismo resultado que obtuvimos antes cuando calculamos el valor p con el método clásico anterior.
%% Cell type:markdown id: tags:
# Pruebas A/B
%% Cell type:markdown id: tags:
Las pruebas A/B son esencialmente un simple ensayo aleatorio. Los ensayos aleatorios se consideran (normalmente) el diseño de estudio estándar para evaluar la eficacia de nuevos tratamientos médicos, pero también se utilizan mucho más ampliamente en la investigación experimental.
Por ejemplo, cuando alguien visita un sitio web, el sitio le envía a una de dos (o posiblemente más) páginas de aterrizaje o de inicio diferentes, y la que se le envía se elige al azar. El objetivo es determinar qué versión de la página genera un resultado superior, por ejemplo, qué página genera más ingresos por publicidad o qué página lleva a una mayor proporción de visitantes a seguir visitando el sitio.
La idea clave es que, como aleatorizamos la página de destino (o el tratamiento en el caso de un ensayo clínico aleatorio) a la que acude alguien, después de un gran número de visitantes, los grupos de personas que visitaron las dos páginas son completamente comparables en lo que respecta a todas las características (por ejemplo, edad, sexo, ubicación y cualquier otra cosa que se le ocurra). Como los dos grupos son comparables, podemos comparar los resultados (por ejemplo, la cantidad de ingresos por publicidad) entre los dos grupos para obtener una evaluación imparcial y justa de la eficacia relativa (en términos de nuestro resultado definido) de los dos diseños.
Supongamos por el momento que hemos tenido dos visitantes en nuestro sitio, y que uno de ellos ha sido asignado aleatoriamente a la página A, y el otro a la página B (nótese que es totalmente posible, con una simple aleatorización, que ambos visitantes hayan sido enviados a la página A). Supongamos a continuación que el visitante de la página A ha generado ingresos, pero el de la página B no ha generado ingresos. ¿Debemos concluir que la página A es superior a la página B en términos de generación de ingresos? Por supuesto que no. Dado que sólo hemos tomado una muestra de dos visitantes, es perfectamente posible que el visitante de la página A hubiera generado ingresos aunque se le hubiera enviado a la página B, tal vez porque está muy interesado en el contenido del sitio, mientras que el visitante de la página B no estaba especialmente interesado en el contenido del sitio y nunca iba a generar ingresos. Podemos superar este problema realizando la prueba A/B para un número de visitantes suficientemente grande, de manera que la probabilidad de que se produzca el escenario descrito anteriormente sea suficientemente pequeña.
Escenario: Realizamos una prueba A/B con dos versiones diferentes de una página web, a y b, para la que contamos el número de visitantes y si convierten o no. Podemos resumirlo en una tabla de contingencia que muestre la distribución de frecuencias de los eventos:
%% Cell type:code id: tags:
``` python
data = pd.DataFrame({
'version': ['A', 'B'],
'conversion_negativa': [4514, 4473],
'conversion_positiva': [486, 527]
})[['version', 'conversion_negativa', 'conversion_positiva']]
data
```
%% Output
version conversion_negativa conversion_positiva
0 A 4514 486
1 B 4473 527
%% Cell type:markdown id: tags:
Es trivial calcular el índice de conversión de cada versión, 486/(486 + 4514) = 9,72% para la a y 10,5% para la b. Sin embargo, con una diferencia tan relativamente pequeña, ¿podemos decir de forma convincente que la versión b convierte mejor? Para comprobar la significación estadística de un resultado como éste, se puede utilizar una prueba de hipótesis.
%% Cell type:markdown id: tags:
## Comparando dos proporciones
%% Cell type:markdown id: tags:
Formalicemos un poco nuestro proceso de pensamiento, supongamos que hemos obtenido datos de n visitantes, $n_A$ de los cuales han sido enviados (aleatoriamente) a la página A, y $n_B$ de los cuales han sido enviados a la página B. Además, dejemos que $X_A$ y $X_B$ denoten el número de visitantes para los que hemos obtenido un resultado "exitoso" en los dos grupos. La proporción de éxitos en los dos grupos viene dada por $\hat{p_A} = X_A/n_A$ y $\hat{p_B} = X_B/n_B$ respectivamente. La diferencia estimada en las tasas de éxito viene dada por la diferencia de proporciones: $\hat{p_A} - \hat{p_B}$:
Para evaluar si tenemos pruebas estadísticas de que las tasas de éxito de las dos páginas son realmente diferentes, podemos realizar una prueba de hipótesis. La hipótesis nula que queremos comprobar es que las tasas de éxito reales de las dos páginas son iguales, mientras que la alternativa es que difieren (una es mayor que la otra). Si $p_A$ = la proporción de la población de la página A de la que obtuvimos un resultado satisfactorio y $p_B$ = la proporción de la población de la página B de la que obtuvimos un resultado satisfactorio, entonces nos interesa probar la siguiente hipótesis:
$$
\begin{align}
H_0:p_A = p_B \text{ versus } H_A: p_A \neq p_B
\end{align}
$$
O dicho de otro modo, la hipótesis nula dice que los factores "tipo de página" y "resultado" son estadísticamente independientes entre sí. En palabras, esto significa que saber a qué página se envía a alguien no dice nada sobre la probabilidad de que tenga un resultado satisfactorio. Ahora que sabemos qué prueba de hipótesis nos interesa, tendremos que derivar la estadística de prueba adecuada.
Una un tests estadístico es una métrica única que puede utilizarse para evaluar la hipótesis nula y la forma estándar de obtener esta métrica es calcular la puntuación z que mide cuántas desviaciones estándar por debajo o por encima de la media de la población está una puntuación bruta:
$$
\begin{align}
z = \frac{x - \mu}{SE}
\end{align}
$$
donde:
- $\mu$ el el valor medio
- $SE$ o aveces denotado como $\sigma$ se refiere al error estandar, calculado por $\frac{s}{\sqrt{n}}$, donde $s$ denota el error estandard y $n$ el tamaño de la muestra.
El siguiente enlace contiene un ejemplo de cómo se aplica esto en las pruebas de hipótesis de proporción para aquellos que se sientan incómodos con este concepto. Notas: Eberly College of Science STAT 414/415: Prueba sobre proporciones](https://onlinecourses.science.psu.edu/stat414/node/265)
Para nuestra prueba, la métrica subyacente es una variable binaria sí/no (evento), lo que significa que el **test estadístico** apropiado es una prueba para las diferencias en las proporciones:
$$
\begin{align}
Z = \frac{ (\hat{p_A} - \hat{p_B}) - (p_A - p_B) }{SE(p_A - p_B)}
\end{align}
$$
El **test estadístico** tiene sentido porque mide la diferencia entre las proporciones observadas y la proporción estimada, estandarizada por una estimación del error estándar de esta cantidad.
Para calcular el **test estadístico**, primero tenemos que encontrar la desviación estándar/varianza de $p_A - p_B$:
$$
\begin{align}
Var(p_A - p_B)
&= Var(p_A) + Var(p_B) \\
&= \frac{p_A (1 - p_A)}{n_A} + \frac{p_B (1 - p_B)}{n_B} \\
&= p (1 - p) \left( \frac{1}{n_A} + \frac{1}{n_B} \right)
\end{align}
$$
- El primer paso se deriva del hecho de que, dado que sabemos
- La varianza de una variable aleatoria X se define como $Var(X) = E[X^2] - E[X]^2$
- La covarianza entre dos variables aleatorias X e Y se define como $Cov(X, Y) = E[(X - u_x)(y - u_y)] = E[XY] - E[X]E[Y]$
- Al realizar la prueba de hipótesis, sabemos que los dos grupos deben ser independientes entre sí, es decir, la covarianza entre ambos debe ser 0
$$
\begin{align}
Var(X - Y)
&= Var(X) + Var(Y) - 2 Cov(X, Y)
\end{align}
$$
- Estamos utilizando la propiedad de que la varianza de una proporción binomial viene dada por $Var(p_A) = p_A (1 - p_A) / n_A$, lo mismo se puede aplicar para el grupo B
- El tercer paso proviene del hecho de que si suponemos que la hipótesis nula, $p_A = p_B$ es verdadera, entonces las proporciones de la población son iguales a algún valor común $p$, es decir, $p_A = p_B = p$. Dado que no conocemos la proporción poblacional común supuesta $p$ más de lo que conocemos las proporciones $p_A$ y $p_B$ de cada población, podemos estimar $p$ utilizando la proporción de "éxitos" en las dos combinadas, $\hat{p} = (X_A + X_B)/(n_A + n_B)$, que se conoce comúnmente como la **probabilidad conjunta**.
Durante el tercer paso, utilizamos el hecho de que si asumimos que la hipótesis nula es verdadera, entonces $p_A = p_B$, esto también significa $p_A - p_B = 0$. Dada toda esta información, la fórmula para nuestro estadístico de prueba se convierte ahora en
$$
\begin{align}
Z
&= \frac{ (\hat{p_A} - \hat{p_B}) - (p_A - p_B) }{SE(p_A - p_B)} \\
&= \frac{ (\hat{p_A} - \hat{p_B}) - 0 }{\sqrt{\hat{p} (1 - \hat{p}) \left( \frac{1}{n_A} + \frac{1}{n_B} \right)}}
\end{align}
$$
Where $\hat{p} = (X_A + X_B)/(n_A + n_B)$
%% Cell type:code id: tags:
``` python
def test_de_dos_proporciones(exito_a, tamano_a, exito_b, tamano_b):
"""
Prueba A/B para dos proporciones; dado un éxito un tamaño de prueba
del grupo A y B calcular su puntuación z y su valor p
Parametros
----------
exito_a, exito_b : int
Número de éxitos en cada grupo
tamano_a, tamano_b : int
Tamaño, o número de observaciones en cada grupo
Returns
-------
zscore : float
estadística de la prueba z de dos proporciones
pvalue : float
p-value para el test estadístico de dos proporciones
"""
prop_a = exito_a / size_a
prop_b = exito_b / size_b
prop_pooled = (exito_a + exito_b) / (tamano_a + tamano_b)
var = prop_pooled * (1 - prop_pooled) * (1 / size_a + 1 / size_b)
zscore = np.abs(prop_b - prop_a) / np.sqrt(var)
one_side = 1 - stats.norm(loc = 0, scale = 1).cdf(zscore)
pvalue = one_side * 2
return zscore, pvalue
```
%% Cell type:code id: tags:
``` python
exito_a = 486
tamano_a = 5000
exito_b = 527
tamano_b = 5000
zscore, pvalue = test_de_dos_proporciones(success_a, size_a, success_b, size_b)
print('valor z = {:.3f}, pvalue = {:.3f}'.format(zscore, pvalue))
```
%% Output
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-17-5ae74c47944f> in <module>
4 tamano_b = 5000
5
----> 6 zscore, pvalue = test_de_dos_proporciones(success_a, size_a, success_b, size_b)
7 print('valor z = {:.3f}, pvalue = {:.3f}'.format(zscore, pvalue))
NameError: name 'success_a' is not defined
%% Cell type:code id: tags:
``` python
# o podemos usar la implementación de statsmodels
# donde pasamos el éxito (llaman al argumento counts)
# y el número total de cada grupo (llaman al argumento nobs,
# número de observaciones)
counts = np.array([486, 527])
nobs = np.array([5000, 5000])
zscore, pvalue = proportions_ztest(counts, nobs, alternative = 'two-sided')
print('zscore = {:.3f}, pvalue = {:.3f}'.format(zscore, pvalue))
```
%% Cell type:markdown id: tags:
Si nuestro **p-value** no es inferior al umbral de 0,05 que se suele utilizar, la estadística de la prueba nos indica que no tenemos pruebas sólidas contra nuestra hipótesis nula, es decir, que no tenemos pruebas sólidas de que las dos páginas no sean igual de eficaces.
Aparte de escupir el **p-value**, también veremos cómo formar un intervalo de confianza para $\hat{p_A} - \hat{p_B}$. Si el número de ensayos en ambos grupos es grande, y el número observado de éxitos no es demasiado pequeño, podemos calcular un intervalo de confianza del 95% utilizando la fórmula:
$$
\begin{align}
\text{point estimate} \pm z * SE
&= (\hat{p_A} - \hat{p_B}) \pm z * \frac{p_A (1 - p_A)}{n_A} + \frac{p_B (1 - p_B)}{n_B}
\end{align}
$$
Tenga en cuenta que al calcular el intervalo de confianza porque ya no tenemos la suposición de que $p_A = p_B$ de nuestra hipótesis nula, por lo que no podemos aprovechar esta propiedad y utilizar la probabilidad agrupada.
%% Cell type:code id: tags:
``` python
def test_de_dos_proporciones_cint(exito_a, tamano_a, exito_b, tamano_b, significance = 0.05):
"""
Prueba A/B para dos proporciones;
dado un éxito un tamaño de prueba del grupo A y B calcular
su intervalo de confianza;
el intervalo de confianza resultante coincide con la función prop.test de R
Parametros
----------
exito_a, exito_b : int
Número de éxitos en cada grupo
tamano_a, tamano_b : int
Tamaño, o número de observaciones en cada grupo
significance : float, default 0.05
A menudo se denota como alfa. Regula la probabilidad de un falso positivo.
Un nivel de significación de 0,05 significa que hay un 5% de posibilidades de
un falso positivo. En otras palabras, nuestro nivel de confianza es
1 - 0.05 = 0.95
Returns
-------
prop_diff : float
Diferencia entre las dos proporciones
confint : 1d ndarray
Intervalo de confianza del test estadístico de las dos proporciones
"""
prop_a = exito_a / tamano_a
prop_b = exito_b / tamano_b
var = prop_a * (1 - prop_a) / tamano_a + prop_b * (1 - prop_b) / tamano_b
se = np.sqrt(var)
# z critical value
confidence = 1 - significance
z = stats.norm(loc = 0, scale = 1).ppf(confidence + significance / 2)
# standard formula for the confidence interval
# point-estimtate +- z * standard-error
prop_diff = prop_b - prop_a
confint = prop_diff + np.array([-1, 1]) * z * se
return prop_diff, confint
```
%% Cell type:code id: tags:
``` python
prop_diff, confint = test_de_dos_proporciones_cint(success_a, size_a, success_b, size_b)
print('Diferencia estimada:', prop_diff)
print('Intervalo de confianza:', confint)
```
%% Cell type:markdown id: tags:
Hasta ahora, hemos utilizado 5000 como el número total de observaciones/muestras que intervienen en el proceso de las pruebas A/B. La siguiente cuestión que abordaremos es, en los escenarios del mundo real, cuántas observaciones necesitamos para extraer un veredicto válido sobre el resultado de la prueba. Esto nos lleva a nuestro siguiente tema de **poder estadístico**.
%% Cell type:markdown id: tags:
## Poder estadístico
%% Cell type:markdown id: tags:
En el mundo de las pruebas de hipótesis, rechazar la hipótesis nula cuando en realidad es verdadera se denomina error de tipo 1, a menudo denotado como $\alpha$. Cometer un error de tipo 1 es un falso positivo porque acabamos recomendando algo que no funciona. Por el contrario, un error de tipo 2, a menudo denotado como $\beta$, se produce cuando no rechazamos la hipótesis nula cuando en realidad es falsa. Se trata de un falso negativo porque acabamos cruzados de brazos cuando deberíamos haber actuado. Debemos tener en cuenta ambos tipos de errores al elegir el tamaño de la muestra.
Dos probabilidades importantes relacionadas con el error de tipo 1 y de tipo 2 son:
- **Nivel de significación:** Gobierna la probabilidad de un falso positivo. Un nivel de significación de 0,05 significa que hay un 5% de posibilidades de un falso positivo. La elección del nivel de significación es una tarea arbitraria, pero para muchas aplicaciones se elige un nivel del 5%, sin mejor razón que la de ser convencional
- **Poder estadístico** Un poder estadístico de 0,80 significa que hay un 80% de posibilidades de que, si hubiera un efecto, lo detectáramos (o un 20% de posibilidades de que no lo detectáramos). En otras palabras, equivale a 1$ - \beta$. No hay normas formales para la el poder estadístico, esto depende de la tarea a mano y el area de investigación
| Escenario | $H_0$ es verdadera | $H_0$ es falsa |
|:--------------:|:----------------------------------:|:-------------------------:|
|Acepta $H_0$ | Decisión correcta | Error de tipo 2 (1 - potencia) | Acepta $H_0$ | Decisión correcta
|Acepta $H_0$ | Decisión correcta | Error de tipo 2 (1 - poder estadístico) |
| Rechazar $H_0$ | Error de tipo 1 (nivel de significación) | Decisión correcta
Los conceptos de poder estadístico y nivel de significación pueden parecer algo enrevesados a primera vista. Una buena forma de hacerse una idea de la mecánica subyacente es trazar la distribución de probabilidad de $Z$ suponiendo que la hipótesis nula es verdadera. A continuación, haga lo mismo suponiendo que la hipótesis alternativa es verdadera, y superponga los dos gráficos.
Considere el siguiente ejemplo: $H_0: p_A = p_B, H_1: p_A > p_B$. En este caso se ha elegido una prueba unilateral para simplificar el gráfico.
- Tamaño total de la muestra, N=5.000 (suponiendo tamaños de muestra iguales para los grupos de control y experimento, lo que significa exactamente 2.500 en cada grupo)
- Digamos que hemos decidido que necesitamos observar una diferencia de 0,02 para estar satisfechos de que la intervención haya funcionado (es decir, suponiendo que nuestra línea de base original, $p_B$ era de 0,08, entonces queremos que $p_A = 0,10$). Discutiremos cómo tomar esta decisión más adelante en este artículo.
%% Cell type:code id: tags:
``` python
def plot_poder_estadistico(min_diff, prob_b, tamano_a, tamano_b, significance = 0.05):
"""illustrating power through a one-tailed hypothesis test"""
# obtain the z-score for the minimum detectable
# difference using proportion_ztest
prob_a = prob_b + min_diff
count_a = tamano_a * prob_a
count_b = tamano_b * prob_b
counts = np.array([count_a, count_b])
nobs = np.array([tamano_a, tamano_b])
zscore, _ = proportions_ztest(counts, nobs, alternative = 'larger')
# distribution for the null hypothesis, h0
# and alternative hypothesis, h1
h0 = stats.norm(loc = 0, scale = 1)
h1 = stats.norm(loc = zscore, scale = 1)
# points that are greater than the zscore for the
# specified significance level
x = np.linspace(-5, 6, num = 100)
threshold = h0.ppf(1 - significance)
mask = x > threshold
# power is the area after the threshold, i.e.
# 1 - the cumulative distribution function of that point
power = np.round(1 - h1.cdf(threshold), 2)
hypotheses = [h1, h0]
labels = ['$H_1$ es verdadera', '$H_0$ es verdadera']
for hypothesis, label in zip(hypotheses, labels):
y = hypothesis.pdf(x)
line = plt.plot(x, y, label = label)
plt.fill_between(x = x[mask], y1 = 0.0, y2 = y[mask],
alpha = 0.2, color = line[0].get_color())
title = 'p1: {}, p2: {}, tamaño 1: {}, tamaño 2: {}, poder estadístico: {}'
plt.title(title.format(prob_a, prob_b, tamano_a, tamano_b, power))
plt.legend()
plt.tight_layout()
plt.show()
```
%% Cell type:code id: tags:
``` python
prob_b = 0.08
min_diff = 0.02
tamano_a = 2500
tamano_b = 2500
plot_poder_estadistico(min_diff, prob_b, size_a, size_b)
```
%% Cell type:markdown id: tags:
El área azul sombreada denota la región de significación, mientras que el área azul sombreada denota el poder estadístico (nótese que incluye el área verde sombreada). Obsérvese que si elegimos un N más pequeño, o una diferencia de probabilidad más pequeña entre el grupo de control y el grupo del experimento, el poder estadístico disminuye (el área azul sombreada disminuye), lo que significa que si hay realmente un cambio, hay un porcentaje menor de posibilidades de detectarlo.
%% Cell type:code id: tags:
``` python
# smaller N
prob_b = 0.08
min_diff = 0.02
tamano_a = 1250
tamano_b = 1250
plot_poder_estadistico(min_diff, prob_b, size_a, size_b)
```
%% Cell type:code id: tags:
``` python
# smaller probability difference
prob_b = 0.08
min_diff = 0.001
size_a = 2500
size_b = 2500
plot_power(min_diff, prob_b, size_a, size_b)
```
%% Cell type:markdown id: tags:
El siguiente enlace ilustra la potencia de una prueba de hipótesis de dos caras para los interesados. [Youtube: Calculating Power and the Probability of a Type II Error (A Two-Tailed Example)](https://www.youtube.com/watch?v=NbeHZp23ubs)
%% Cell type:markdown id: tags:
## Determinando el tamaño de la muestra
%% Cell type:markdown id: tags:
Digamos que hemos seguido la regla del pulgar y hemos exigido que el nivel de significación sea del 5% y que lel poder estadístico sea del 80%. Esto significa que ya hemos especificado los dos componentes clave del analisis.
- Una regla de decisión sobre cuándo rechazar la hipótesis nula. Rechazamos la nula cuando el valor p es inferior al 5%.
- Nuestra tolerancia para cometer un error de tipo 2 (1-80%=20%).
Para resolver realmente la ecuación de encontrar el tamaño de muestra adecuado, también necesitamos especificar la diferencia detectable, es decir, el nivel de impacto que queremos poder detectar con nuestra prueba.
Para explicar la dinámica que hay detrás, volveremos a la definición del poder estadístico: es la probabilidad de rechazar la hipótesis nula cuando es falsa. Por lo tanto, para calcular la potencia, tenemos que definir qué significa "falso" para nosotros en el contexto del estudio. En otras palabras, ¿cuál es el impacto, es decir, la diferencia entre la prueba y el control, que necesitamos observar para rechazar la hipótesis nula y concluir que la acción funcionó?
Consideremos dos ejemplos ilustrativos: si pensamos que una reducción de la tasa de eventos de, digamos, 10-10 es suficiente para rechazar la hipótesis nula, entonces necesitamos un tamaño de muestra muy grande para obtener el poder estadístico del 80%. Esto es bastante fácil de deducir de los gráficos anteriores: si la diferencia en las tasas de eventos entre la prueba y el control es un número pequeño como 10-10 , las distribuciones de probabilidad nula y alternativa serán casi indistinguibles. Por lo tanto, tendremos que aumentar el tamaño de la muestra para desplazar la distribución alternativa hacia la derecha y ganar potencia. Por el contrario, si sólo necesitamos una reducción de 0,02 para tener éxito, podemos conformarnos con un tamaño de muestra mucho menor.
Cuanto menor sea la diferencia detectable, mayor será el tamaño de la muestra necesario
Así es como podríamos realizar una prueba de potencia en python:
%% Cell type:code id: tags:
``` python
import statsmodels.stats.api as sms
def calcula_tamano_muestra(prop1, min_diff, significance = 0.05, poder = 0.8):
"""
Calcula el tamaño de la muestra requerido para una prueba A/B de dos proporciones;
el resultado coincide con pwr.2p.test de R del paquete pwr
Parameters
----------
prop1 : float
La proporción de referencia, por ejemplo, la tasa de conversión
min_diff : float
Diferencia mínima detectable
significance : float, default 0.05
A menudo se denota como alfa. Regula la probabilidad de un falso positivo.
Un nivel de significación de 0,05 significa que hay un 5% de posibilidades de
un falso positivo. En otras palabras, nuestro nivel de confianza es
1 - 0.05 = 0.95
power : float, default 0.8
A menudo se denota como beta. Una potencia de 0,80 significa que hay un 80% de
probabilidad de que, si hubiera un efecto, lo detectáramos
(o un 20% de probabilidades de no detectar el efecto)
Returns
-------
sample_size : int
Tamaño de la muestra necesario para cada grupo del experimento
Referencias
----------
R pwr package's vignette
- https://cran.r-project.org/web/packages/pwr/vignettes/pwr-vignette.html
Stackoverflow: Is there a python (scipy) function to determine parameters
needed to obtain a target power?
- https://stackoverflow.com/questions/15204070/is-there-a-python-scipy-function-to-determine-parameters-needed-to-obtain-a-ta
"""
prop2 = prop1 + min_diff
tamano_efecto = sms.proportion_effectsize(prop1, prop2)
tamano_muestra = sms.NormalIndPower().solve_power(
tamano_efecto, power = poder, alpha = significance, ratio = 1)
return tamano_muestra
```
%% Cell type:code id: tags:
``` python
tamano_muestra = calcula_tamano_muestra(prop1 = 0.1, min_diff = 0.02)
print('tamaño de la muestra requerido para obtener un resultado significativo:', tamano_muestra)
```
%% Cell type:markdown id: tags:
Tenga en cuenta que el resultado impreso es el tamaño de la muestra necesario para cada grupo.
A diferencia del nivel de significación y el poder estadístico, no hay valores que podamos utilizar para la diferencia detectable. La clave está en definir qué significa "pay off" para el estudio en cuestión, lo que depende de cuál sea el evento adverso, así como del coste de la acción. Dos principios rectores:
- Evitar el despilfarro en el muestreo Digamos que hace falta una diferencia absoluta de 0,02 entre la prueba y el control para que el tratamiento sea rentable. En este caso, aspirar a una diferencia detectable de 0,01 sólo conduciría a una mayor precisión de la que realmente necesitamos. ¿Por qué tener la capacidad de detectar 0,01 si realmente no nos importa una diferencia de 0,01? En muchos casos, el muestreo para obtener una precisión innecesaria puede ser costoso y una pérdida de tiempo
- Evitar oportunidades perdidas Por el contrario, si estamos analizando una métrica sensible en la que pequeños cambios pueden tener un gran impacto, por ejemplo, las campañas de correo electrónico, tenemos que aspirar a una pequeña diferencia detectable. Si elegimos un tamaño de muestra insuficiente, podemos acabar cruzados de brazos y perder una oportunidad (error de tipo 2)
Por lo tanto, la elección de la diferencia mínima detectable debe ser un análisis/discusión interfuncional entre el científico de datos y la parte interesada del negocio. Una vez que existe un rango viable para la diferencia detectable, podemos evaluar el tamaño de la muestra necesaria para cada opción. Por ejemplo, digamos que p1=0,10 y queremos que la diferencia detectable esté entre 0,01 y 0,03. Evidentemente, preferiríamos poder detectar una diferencia de 0,01, pero puede ser demasiado costoso y, por tanto, queremos evaluar también opciones más conservadoras.
%% Cell type:code id: tags:
``` python
# calcular el tamaño de la muestra requerido
# para un rango de diferencia mínima detectable
tamano_muestras = []
min_diffs = np.arange(0.01, 0.03, 0.001)
for min_diff in min_diffs:
tamano_muestra = calcula_tamano_muestra(prop1 = 0.1, min_diff = min_diff)
tamano_muestras.append(tamano_muestras)
plt.plot(min_diffs, tamano_muestras)
plt.title('Tamaño de la muestra necesaria para detectar la diferencia mínima')
plt.ylabel('Tamaño de la muestra')
plt.xlabel('Diferencia mínima')
plt.tight_layout()
plt.show()
```
%% Cell type:markdown id: tags:
A partir del gráfico, podemos ver que necesitamos aproximadamente 10 veces más observaciones para obtener una diferencia detectable de 0,01 en comparación con 0,03.
%% Cell type:markdown id: tags:
# Ejercicio
Todos vimos la película del Titanic y vimos la parte en la que los ricos empezaron a dar dinero para tener prioridad en los botes de seguridad. Podemos entonces formular la hipótesis de que los ricos del Titanic tenían una tasa de supervivencia más alta que los demás. Como no podemos confiar sólo en una película para sacar conclusiones, debemos obtener datos.
Vamos a utilizar el conjunto de datos que proporciona [Kaggle aquí](https://www.kaggle.com/c/titanic/data).
1. Subir los datos al notebook
2. Hacer una exploración de las variables presentes en el conjunto de datos.
3. Usar los conceptos y funciones definidas en este notebook para realizar una prueba de hipotesis, que pruebe o desmienta si los pasajeros mas ricos del Titanic tenian mayor tasa de supervivencia.
%% Cell type:markdown id: tags:
# Reference
- [Youtube: Beautiful A/B Testing](https://www.youtube.com/watch?v=EvDg7ssY0M8)
- [Notebook: Statistics for Hackers](http://nbviewer.jupyter.org/github/croach/statistics-for-hackers/blob/master/statistics-for-hackers.ipynb)
- [Blog: What Are P-Values?](https://prateekvjoshi.com/2013/12/07/what-are-p-values/)
- [Blog: How to work with A/B test data](https://medium.com/@carsonforter/how-to-work-with-a-b-test-data-96121b89d1a4)
- [Blog: Interpreting A/B Test using Python](http://okomestudio.net/biboroku/?p=2375)
- [Blog: So, You Need a Statistically Significant Sample?](http://multithreaded.stitchfix.com/blog/2015/05/26/significant-sample/)
- [Blog: How to Build a Strong A/B Testing Plan That Gets Results](https://conversionxl.com/how-to-build-a-strong-ab-testing-plan-that-gets-results/)
- [Blog: A/B testing and Pearson's chi-squared test of independence](http://thestatsgeek.com/2013/07/22/ab-testing/)
- [Blog: A/B testing - confidence interval for the difference in proportions using R](http://thestatsgeek.com/2014/02/15/ab-testing-confidence-interval-for-the-difference-in-proportions-using-r/)
- [Blog: Python for Data Analysis Part 23: Point Estimates and Confidence Intervals](http://hamelg.blogspot.com/2015/11/python-for-data-analysis-part-23-point.html)
- [Notes: MOST winning A/B test results are illusory](http://www.qubit.com/sites/default/files/pdf/mostwinningabtestresultsareillusory_0.pdf)
- [Notes: Eberly College of Science STAT 414/415 Comparing Two Proportions](https://onlinecourses.science.psu.edu/stat414/node/268)
- [Quora: When should A/B testing not be trusted to make decisions?](https://www.quora.com/When-should-A-B-testing-not-be-trusted-to-make-decisions)
- [Forbes: How To Do A/B Testing Right And Avoid The Most Common Mistakes Marketers Make](https://www.forbes.com/sites/sujanpatel/2015/10/29/how-to-do-ab-testing-right-and-avoid-the-most-common-mistakes-marketers-make/)
- [Paper: R. Kohavi, A. Deng, B. Frasca, R. Longbotham, T. Walker, Y. Xu (2012) Trustworthy Online Controlled Experiments: Five Puzzling Outcomes Explained](http://notes.stephenholiday.com/Five-Puzzling-Outcomes.pdf)
- [Slideshare: 4 Steps Toward Scientific A/B Testing](https://www.slideshare.net/RJMetrics/4-steps-toward-scientific-ab-testing)
%% Cell type:code id: tags:
``` python
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment