<jupyter_start><jupyter_text>Introducción a la estadística (Parte 2)  Introducción En la lección anterior conocimimos las medidas estadísticas comúnmente empleadas para determinar variabilidad y relación entre variables. En esta lección, nos enfocaremos en aquellas que podemos emplear sobre distribuciones y cómo probar hipótesis.  Cargando nuestros módulos<jupyter_code>import pandas as pd
import numpy as np
import statsmodels.api as sm
import scipy.stats.distributions as dist
import seaborn as sns<jupyter_output><empty_output><jupyter_text>Distribuciones Una de las mejores maneras de describir una variable es reportar los valores que aparecen en el dataset relacionados con dicha viariable y la cantida de veces que aparece cada uno. A este tipo de descripción la llamamos **distribución** de una variable. La forma más común de representar a una distribución es mediante un histograma, la cual es una gráfica que muestra la frecuencia de cada valor de la variable.<jupyter_code>iris = sns.load_dataset('iris')
iris
sns.histplot(iris["sepal_length"] , color="skyblue", label="Sepal Length")<jupyter_output><empty_output><jupyter_text>También puedes utilizar simplemente un contador para obtener las frecuencias de los valores en un diccionario donde cada clave es un valor de la variable y cada valor es la frecuencia<jupyter_code>counter = Counter(iris['sepal_length'])
counter<jupyter_output><empty_output><jupyter_text>Si cuentas con pandas instalado, puedes contabilizarlos con el método value_counts()<jupyter_code>iris.value_counts('sepal_length')
pd.value_counts(iris['sepal_length'])<jupyter_output><empty_output><jupyter_text>Métricas sobre distribuciones  Percentiles Los percentiles son una forma de obtener el valor que corresponde a un cierto porcentaje de los datos ordenados en una distribución, de tal manera que no importa si la distribución es asimétrica, el percentil nos permite hacer el "corte" en la posición porcentual que requerimos. La mediana, puede considerarse un "nombre especial" para el percentil 50, esto significa que el valor de la mediante siempre es mayor que el 50% de los datos ordenados. Lo mismo se puede decir de cualquier otro percentil, es decir, si calculas el percentil 25, eso quiere decir que acabas de encontrar un valor en los datos que es mayor que el 25% de los datos ordenados.<jupyter_code># Vamos a utilizar nuevamente el dataset 'iris'
iris
# Especifica qué percentiles deseas obtener
percentiles = np.array([25, 50, 75])

# Obtenemos los datos para la distribución
versicolor_petal_length = iris.query('species=="versicolor"').loc[:,'petal_length']

# Calculamos los percentiles: ptiles_vers
ptiles_vers = np.percentile(versicolor_petal_length, percentiles)

print(ptiles_vers)<jupyter_output>[4.   4.35 4.6 ]<jupyter_text>Visualizando percentiles mediante histograma<jupyter_code># Plot the ECDF
_ = versicolor_petal_length.plot(kind='hist', figsize=(10, 8), linewidth=2, color='whitesmoke', edgecolor='gray')
_ = plt.xlabel('Versicolor petal length (cm)')
_ = plt.ylabel('Frecuencia')

names = ['25th percentile', '50th percentile', '75th percentile']
colors = ['green', 'blue', 'orange']
for measurement, name, color in zip(ptiles_vers, names, colors):
    plt.axvline(x=measurement, linestyle='--', linewidth=2.5, label='{0} at {1}'.format(name, measurement), c=color)

plt.legend()<jupyter_output><empty_output><jupyter_text>Vamos a corroborar con un boxplot<jupyter_code>sns.boxplot( y=versicolor_petal_length )<jupyter_output><empty_output><jupyter_text>Outliers (valores atípicos) Cuando miramos un histograma es muy fácil identificar los valores más comunes en la distribución, pero los outliers no siempre quedan a la vista. Antes de continuar, siempre es buena idea revisar si tenemos valores atípicos, los cuales son valores extremos que bien pueden ser errores en los registros, o quizá sean reportes precisos de eventos atípicos. Podemos identificar outliers muy fácilmente con gráficas de caja La mejor manera de darle manejo a los datos atípicos  Hallar outliers con boxplots<jupyter_code>my_pal = {"versicolor": "g", "setosa": "b", "virginica":"m"}
sns.boxplot( x=iris["species"], y=iris["sepal_length"], palette=my_pal)<jupyter_output><empty_output><jupyter_text>Hallar outliers con z-score<jupyter_code>data = iris.query('species=="virginica"').loc[:,'sepal_length']
mean = np.mean(data)
std = np.std(data)
print('Media de longitud del sépalo para la especie Virginica: ', mean)
print('Desviación estándar: ', std)
threshold = 2.5
outlier = []
for i in data:
    z = (i-mean)/std
    if z > threshold or z < -threshold:
        outlier.append(i)
print('', outlier)<jupyter_output>[4.9]<jupyter_text>Pruebas de hipótesis  Prueba de hipótesis para una muestra Esta es la prueba de hipótesis más básica. La mayoría de las veces no tenemos un valor fijo específico para comparar. Pero si es así, esta es la prueba de hipótesis más simple. Voy a comenzar con una prueba de hipótesis de una proporción. Usé el conjunto de datos Heart de Kaggle para esta demostración. No dude en descargar el conjunto de datos para su práctica. Aquí importo los paquetes y el conjunto de datos:<jupyter_code># https://www.kaggle.com/johnsmith88/heart-disease-dataset
df = pd.read_csv('data/heart.csv')
df.head()<jupyter_output><empty_output><jupyter_text>La última columna del conjunto de datos es "target". Que nos dice si la persona tiene una enfermedad cardíaca. La pregunta de investigación para esta sección es: “La proporción de la población de Irlanda que padece una enfermedad cardíaca es del 42%. ¿Hay más personas que padecen enfermedades cardíacas en los EE. UU. ”? Vamos a intentar corroborar esta hipótesis paso por paso:  Paso 1: Determinar la hipótesis nula y las hipótesis alternativas En este problema, la hipótesis nula es que la proporción de la población que padece una enfermedad cardíaca en los EE. UU. sea menor o igual al 42%. Pero si probamos que sea igual, con eso tendremos para corroborar la hipótesis. Por lo tanto, podemos definir p0 como: `p0 = 0.42   Hipótesis nulap > 0.42   Hipótesis alternativa` Veamos si podemos hallar evidencia para refutar la hipótesis nula  Paso 2: Calcular la proporción de la población que tiene una enfermedad cardiovascular Asuma que el dataset de más arriba es una muestra representativa de la poblción de Estados Unidos. Entonces, vamos a calcular la proporción de personas que de hecho tienen una enfermedad cardiovascular.<jupyter_code>p_us = len(df[df['target']==1])/len(df)
p_us<jupyter_output><empty_output><jupyter_text>La proporción de la población de la muestra que tiene enfermedad cardíaca es 0,51 o 51%. Este porcentaje es mayor que la hipótesis nula. Eso es 42% Pero la pregunta es si es significativamente más del 42%. Si tomamos una muestra aleatoria simple diferente, la proporción de población observada actualmente (51%) puede ser diferente. Para averiguar si la proporción de población observada es significativamente mayor que la hipótesis nula, realice una prueba de hipótesis.  Paso 3: Calculando el test estadístico Esta es la fórmula para el test estadístico ![image.png](attachment:cfce43e9-2c6c-4a8d-81f8-832d484f4e02.png) Utilizaremos esta fórmula para el error estándar ![image.png](attachment:62ec3674-7c6e-4842-8134-b7538d3bea7a.png) En esta fórmula, `p0` es 0,42 (según la hipótesis nula) y `n` es el tamaño de la población de la muestra. Ahora calcule el error estándar y las estadísticas de la prueba:<jupyter_code>se = np.sqrt(0.42 * (1-0.42) / len(df))
se<jupyter_output><empty_output><jupyter_text>Encuentre las estadísticas de prueba utilizando la fórmula para la estadística de prueba anterior:<jupyter_code>#Best estimate
be = p_us  #hypothesized estimate
he = 0.42
test_stat = (be - he)/se
test_stat<jupyter_output><empty_output><jupyter_text>Paso 4: Calcule el valor p Esta estadística de prueba también se llama puntuación z. Puede encontrar el valor p de una z_table o puede encontrar el valor p de esta fórmula en Python.<jupyter_code>pvalue = 2*dist.norm.cdf(-np.abs(test_stat))
pvalue<jupyter_output><empty_output><jupyter_text>El valor p es 0,1562. Significa que la proporción de la población de la muestra (46% o 0,46) es 0,1562 errores estándar nulos por encima de la hipótesis nula.  Paso 5: inferir la conclusión del valor p Considere que el nivel de significancia alfa es 5% o 0.05. Un nivel de significancia del 5% o menos significa que existe una probabilidad del 95% o más de que los resultados no sean aleatorios. Aquí el valor p es mayor que nuestro nivel de significancia considerado 0.05. Entonces, no podemos rechazar la hipótesis nula. Eso significa que no hay una diferencia significativa en la proporción de la población que padece una enfermedad cardíaca en Irlanda y los EE. UU.  Pruebas de hipótesis para dos diferentes muestras Las pruebas comparativas se realizan con mucha más frecuencia que una prueba de hipótesis de una sola muestra de la población. Se realiza una prueba de proporciones de dos muestras para evaluar si la proporción poblacional de algunos rasgos difiere entre dos subgrupos.  Paso 1: Determinar la hipótesis nula, la hipótesis alternativa y el nivel significativo (alfa) Aquí, queremos comprobar si existe alguna diferencia entre la proporción de la población de hombres y mujeres que padecen enfermedades cardíacas. Comenzaremos con el supuesto de que no hay diferencia. `H0: p1 - p2 = 0   Hipótesis nula` Esta es nuestra hipótesis nula. Aquí, p1 es la proporción de la población de mujeres con enfermedades cardíacas y p2 es la proporción de la población de hombres que tienen una enfermedad cardíaca. ¿Cuál podría ser la hipótesis alternativa? La hipótesis alternativa puede ser, hay una diferencia. `H1: p1 - p2 != 0   Hipótesis alternativa` Usemos el nivel de significancia de 0.1 o 10%.  Paso 2: Generar una visualización que muestre la proporción de la población de hombres y mujeres con enfermedades cardíacas y la población total de hombres y mujeres.<jupyter_code>df['Gender'] = df.sex.replace({1: "Male", 0: "Female"})
p = df.groupby("Gender")['target'].agg([lambda z: np.mean(z==1), "size"])
p.columns = ["HeartDisease", 'Total']
p<jupyter_output><empty_output><jupyter_text>Paso 3: Calcule la estadística de prueba Usaremos la misma fórmula para el estadístico de prueba que antes. La mejor estimación es p1 - p2. Aquí, p1 es la proporción poblacional de mujeres con enfermedades cardíacas y p2 es la proporción poblacional de hombres con enfermedades cardíacas.<jupyter_code>#La mejor estimación es p1 - p2. Obtenga p1 y p2 de la tabla p anterior
p_fe = p.HeartDisease.Female
print(p_fe)
p_male = p.HeartDisease.Male
print(p_male)<jupyter_output>0.7243589743589743
0.42075736325385693<jupyter_text>El error estándar para la proporción de dos poblaciones se calcula con la siguiente fórmula: ![image.png](attachment:f840f5ca-c43d-43e0-94a7-fbe63e0929e5.png) Aquí, p es la proporción de la población total en la muestra con enfermedad cardíaca. n1 y n2 son los números totales de las poblaciones femenina y masculina de la muestra.<jupyter_code>p_us  # Calculada al inicio del ejemplo anterior
n1 = p.Total.Female
n2 = p.Total.Male
se = np.sqrt(p_us*(1-p_us)*(1/n1 + 1/n2))
print(se)<jupyter_output>0.03392806959170294<jupyter_text>Ahora, use este error estándar y calcule la estadística de prueba.<jupyter_code>#Calculamos la mejor estimación (best estimate - be)
be = p_fe - p_male  # Calculamos la hipótesis estimada
# Nuestra hipótesis nula es p1 - p2 = 0
he = 0 # Calculamos la estadística de prueba
test_statistic = (be - he)/se
test_statistic<jupyter_output><empty_output><jupyter_text>El test_statistic calculado es 8.9483. Eso significa que la diferencia observada en las proporciones de la muestra es 0,296 error estándar estimado por encima del valor hipotetizado.  Paso 4: Calcule el valor p<jupyter_code>pvalue = 2*dist.norm.cdf(-np.abs(test_statistic))
print(pvalue)<jupyter_output>3.607034554789343e-19<jupyter_text>EL valor de p es tremendamente chico. Eso significa que es muy poco probable que los resultados que observemos sean verdaderos considerando que la hipótesis nula es verdadera. Por otro lado, el valor p no es mayor que el nivel de significancia (0.1). Entonces, tenemos suficiente evidencia para rechazar la hipótesis nula. La proporción de la población de hombres con enfermedades del corazón es significativamente diferente de la proporción de la población de mujeres con enfermedades del corazón.  Prueba de hipótesis para una media Este es un proceso de prueba de hipótesis simple. Podemos realizar esta prueba si tenemos un valor medio fijo específico para comparar. Trabajemos en un ejemplo para comprender el proceso. Esta es la pregunta de investigación: "Compruebe si el RestBP medio es superior a 135". Aquí, RestBP es la presión arterial en reposo. Tenemos una columna RestBP en el DataFrame. Resolvamos este problema paso a paso.  Paso 1: enuncie la hipótesis Necesitamos averiguar si la RestBP media es mayor que 135. Supongamos que la RestBP media es menor o igual que 135. Entonces, la hipótesis nula puede ser que la RestBP media sea 135. Porque si podemos probar que la RestBP media es mayor que 135, automáticamente es mayor que 134 o 130. Si encontramos suficiente evidencia para rechazar la hipótesis nula, podemos aceptar que la media de RestBP es mayor que 135. Esta es la hipótesis alternativa para este ejemplo. `H0: mu = 135` `H1: mu > 135` Comprobaremos si podemos rechazar la hipótesis nula usando un **nivel de significancia de 0.05**.  Paso 2: verifique las suposiciones Hay dos supuestos:- La muestra debe ser una muestra aleatoria simple.- Los datos deben distribuirse normalmente. Para fines de demostración, suponga que se trata de una muestra aleatoria simple. Para verificar el segundo supuesto, grafique los datos y observe la distribución.<jupyter_code>sns.distplot(df.trestbps)<jupyter_output>C:\ProgramData\Anaconda3\lib\site-packages\seaborn\distributions.py:2551: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).
  warnings.warn(msg, FutureWarning)<jupyter_text>La distribución no es exactamente normal. Pero está cerca de lo normal. ***La buena noticia es que no debemos preocuparnos por la normalidad de los datos. Porque tenemos un tamaño de muestra suficientemente grande (más de 25 datos).***  Paso 3: Calcule la estadística de prueba Aquí está la fórmula para calcular la estadística de prueba: ![image.png](attachment:d6aab1eb-9528-404a-b7a3-df77485918ef.png) Primero, calcule el error estándar usando la siguiente fórmula: ![image.png](attachment:a5ff6a85-5fe0-4ba7-b646-a6069d164434.png) Aquí, S es la desviación estándar de la muestra y n es el número de muestras.<jupyter_code>std= df.trestbps.std()
n = len(df)
se = std/np.sqrt(n)
se<jupyter_output><empty_output><jupyter_text>Ahora, use este error estándar para encontrar la estadística de prueba:<jupyter_code># La mejor estimación (be)
be = df.trestbps.mean() #Hypothesized estimatehe = 135
be
test_statistic = (be - he)/se
test_statistic<jupyter_output><empty_output><jupyter_text>La estadística de prueba resultó ser 240.54. Mire la fórmula de las estadísticas de prueba. Además, mide la distancia entre la media original y la media hipotética. Y la parte inferior es el error estándar. Entonces, este test_statistic significa que la media de la muestra es un error estándar de 240.54 por encima de la media hipotetizada.  Paso 4: inferir la conclusión de la estadística de prueba Convierta este test_statistic en un valor de probabilidad para ver si esta diferencia es inusual o no. Podemos obtener el valor usando esta fórmula de Python:<jupyter_code>pvalue = 2*dist.norm.cdf(-np.abs(test_statistic))
pvalue<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06605019815059446, 'fraction_numerical': 0.024847455494747435, 'mean_word_length': 5.5289527720739216, 'pattern_counts': {'":': 3, '<': 88, '<?xml version=': 0, '>': 90, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '386327', 'license': 'MIT', 'n_tokens_mistral': 5658, 'n_tokens_neox': 5432, 'n_words': 2037, 'path': 'Kata Fundamentos/IntroStats/Stats2.ipynb', 'repo_name': 'davidandres2010/master-data-ai', 'size': '15897'}