5. Pruebas de hipótesis#
5.1. Distribuciones#
from scipy import stats
import numpy as np
miFD = stats.norm(5,3)
miFD
<scipy.stats._distn_infrastructure.rv_continuous_frozen at 0x7fbc53597490>
x = np.linspace(-5,15,101)
y1 = miFD.pdf(x) # densidad
y2 = miFD.cdf(x) # acumulada
y3 = miFD.ppf(y2) # cuantil
#%matplotlib notebook
import matplotlib.pyplot as plt
plt.figure()
plt.plot(x,y1,'-');
plt.figure()
plt.plot(x,y2,'-');
plt.figure()
x1 = np.linspace(0,1, len(y3))
plt.plot(y2,y3,'-');
Distribución acumulada empírica
x = stats.norm.rvs(loc=0,scale=1,size=1000) # distribucion normal estandar
x = np.sort(x) # odenamos los valores de la variable
n = x.size # tamano de la muestra
y = np.arange(1, n+1) / n # % acumulado
plt.figure()
plt.scatter(x=x, y=y);
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
Text(0, 0.5, 'y')
from statsmodels.distributions.empirical_distribution import ECDF
ecdf = ECDF(x)
ecdf(1.5)
0.9460000000000001
QQ plot
#https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.probplot.html#scipy.stats.probplot
nsample = 100
np.random.seed(7654321)
plt.figure()
x = stats.t.rvs(df=3, size=nsample)
res = stats.probplot(x, plot=plt)
5.2. Test sobre una y dos muestras#
Se introducen dos funciones: stats.ttest_1samp
y stats.wilcoxon
para el test t y el test de Wilcoxon respectivamente. Ambos pueden ser usados para una muestra o dos muestras así como para datos pareados. Note que el test de Wilcoxon para dos muestras es lo mismo que el test de Mann–Whitney.
5.2.1. El test t#
Este test se basa en el supuesto de normalidad de los datos. Es decir que los datos \(x_1\ldots,x_n\) se asumen como realizaciones independientes de variables aleatorias con media \(\mu\) y varianza \(\sigma^2\), \(N(\mu, \sigma^2)\). Se tiene que la hipótesis nula es que \(\mu=\mu_0\).
Se puede estimar los parámetros \(\mu\) y \(\sigma\) por la media \(\bar{x}\) y la desviación estándar \(\sigma\), aunque recuerde que solo son estimaciones del valor real.
Veamos un ejemplo del consuo diario de calorías de 11 mujeres:
daily_intake = [5260,5470,5640,6180,6390,6515,
6805,7515,7515,8230,8770]
Veamos algunas estadísticas de resumen:
stats.describe(daily_intake)
DescribeResult(nobs=11, minmax=(5260, 8770), mean=6753.636363636364, variance=1304445.4545454548, skewness=0.3674679616524392, kurtosis=-0.9757942883536157)
Se podría querer saber si el consumo de energía de las mujeres se desvía de una valor recomendado de \(7725\). Asumiendo que los datos vienen de una distribución normal, el objetivo es hacer una prueba para saber si la media de la distribución es \(\mu = 7725\).
stats.ttest_1samp(daily_intake,7725)
TtestResult(statistic=-2.8207540608310193, pvalue=0.018137235176105812, df=10)
t, pval = stats.ttest_1samp(daily_intake,7725)
t
-2.8207540608310193
pval
0.018137235176105812
5.2.2. Wilcoxon#
(rank, pVal) = stats.wilcoxon(x=(np.array(daily_intake)-7725))
(rank, pVal)
(8.0, 0.0244140625)
Para efectos prácticos, cuando se trata de una muestra, el test t y el de Wilcoxon suelen arrojar resultados muy similares.
5.3. Test t para dos muestras#
Se usa esta prueba con la hipótesis nula de que dos muestras provengan de distribuciones normales con la misma media.
Se puede tener dos enfoques, que las muestras tengan la misma varianza (enfoque clásico) o difieran en varianza.
import numpy as np
from scipy import stats
import os as os
import pandas as pd
#os.chdir('C:/Users/VICTOR/Documents/AnalyticsPython/Data')
energy = pd.read_csv('https://raw.githubusercontent.com/vmoprojs/DataLectures/master/energy.csv')
energy.head()
expend | stature | |
---|---|---|
0 | 9.21 | obese |
1 | 7.53 | lean |
2 | 7.48 | lean |
3 | 8.08 | lean |
4 | 8.09 | lean |
g1 = energy[energy.stature=='obese'].expend.values
g2 = energy[energy.stature=='lean'].expend.values
stats.ttest_ind(g2,g1,equal_var=False)
Ttest_indResult(statistic=-3.855503558973697, pvalue=0.0014106918447179043)
stats.ttest_ind(g2,g1,equal_var=True)
Ttest_indResult(statistic=-3.9455649161549835, pvalue=0.0007989982111700593)
5.3.1. Comparación de varianzas#
Aún cuando en python
se puede hacer la prueba sobre dos muestras sin el supuesto de igualdad en las varianzas, podrías estar interesado en hacer una prueba exclusiva de este supuesto.
import statistics
F = statistics.variance(g2)/statistics.variance(g1)
df1 = len(g1) - 1
df2 = len(g2) - 1
alpha = 0.05
p_value = stats.f.cdf(F, df2, df1)
(F,p_value*2)
(0.7844459792357035, 0.6797459853760682)
5.3.2. Test de Wilcoxon para dos muestras#
u_statistic, pVal = stats.mannwhitneyu(g1, g2)
(u_statistic, pVal*2)
(105.0, 0.004243226771760098)
5.4. Correlación#
Se aborda a continuación medidas de correlación paramétricas y no paramétricas. El coeficiente de correlación es una medida de asociación que varía entre -1 y 1.
5.4.1. Correlación de Pearson#
El coeficiente de correlación empírico es:
La función cor en python
calcula la correlación entre dos o más vectores.
#import os as os
#os.chdir('C:/Users/VICTOR/Documents/AnalyticsPython/Data')
import pandas as pd
datos = pd.read_csv('https://raw.githubusercontent.com/vmoprojs/DataLectures/master/company_sales_data.csv')
datos
month_number | facecream | facewash | toothpaste | bathingsoap | shampoo | moisturizer | total_units | total_profit | |
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2500 | 1500 | 5200 | 9200 | 1200 | 1500 | 21100 | 211000 |
1 | 2 | 2630 | 1200 | 5100 | 6100 | 2100 | 1200 | 18330 | 183300 |
2 | 3 | 2140 | 1340 | 4550 | 9550 | 3550 | 1340 | 22470 | 224700 |
3 | 4 | 3400 | 1130 | 5870 | 8870 | 1870 | 1130 | 22270 | 222700 |
4 | 5 | 3600 | 1740 | 4560 | 7760 | 1560 | 1740 | 20960 | 209600 |
5 | 6 | 2760 | 1555 | 4890 | 7490 | 1890 | 1555 | 20140 | 201400 |
6 | 7 | 2980 | 1120 | 4780 | 8980 | 1780 | 1120 | 29550 | 295500 |
7 | 8 | 3700 | 1400 | 5860 | 9960 | 2860 | 1400 | 36140 | 361400 |
8 | 9 | 3540 | 1780 | 6100 | 8100 | 2100 | 1780 | 23400 | 234000 |
9 | 10 | 1990 | 1890 | 8300 | 10300 | 2300 | 1890 | 26670 | 266700 |
10 | 11 | 2340 | 2100 | 7300 | 13300 | 2400 | 2100 | 41280 | 412800 |
11 | 12 | 2900 | 1760 | 7400 | 14400 | 1800 | 1760 | 30020 | 300200 |
datos.plot('shampoo','bathingsoap',kind = 'scatter')
<Axes: xlabel='shampoo', ylabel='bathingsoap'>
np.corrcoef(datos.shampoo,datos.bathingsoap)
array([[1. , 0.13756757],
[0.13756757, 1. ]])
stats.pearsonr(datos.shampoo,datos.bathingsoap) # devuelve la correlacion y el p-valor
PearsonRResult(statistic=0.1375675688230804, pvalue=0.6698531673457456)
stats.spearmanr(datos.shampoo,datos.bathingsoap) # Spearman's rho
SignificanceResult(statistic=0.2907184843604137, pvalue=0.35929281767147814)
stats.kendalltau(datos.shampoo,datos.bathingsoap) # Kendall's tau
SignificanceResult(statistic=0.10687334289668038, pvalue=0.6304167324095717)
Interpretación de la correlación:
La correlación esta siempre entre -1 y 1. Lo primero que se interpreta es el signo
Directamente proporcional si es positivo, si es negativo pasa lo contrario
En segundo lugar se interpreta es la fuerza de la relación. Si esta más cerca de 1, significa que si aumenta una variable, la otra también.
Números intermedios, reducen la fuerza de la relación.