Introducción al análisis exploratorio de datos

1

¿Qué es y para qué sirve el análisis exploratorio de datos?

2

¿Cómo hacer un análisis exploratorio de datos?

3

Tipos de análisis de datos

4

Tipos de datos y análisis de variables

5

Herramientas de software para el análisis exploratorio de datos

6

Conociendo nuestros datos: palmerpenguins

7

Recolección de datos, limpieza y validación

8

Ejercicio de validación de datos

Quiz: Introducción al análisis exploratorio de datos

Análisis univariado

9

Explorando una variable categórica: conteos y proporciones

10

Estadística descriptiva aplicada: medidas de tendencia central

11

Estadística descriptiva aplicada: medidas de dispersión

12

Ejercicio de obtención de medidas de dispersión

13

Estadística descriptiva aplicada: distribuciones

14

Estadística descriptiva aplicada: funciones de densidad de probabilidad

15

Bonus: Teorema del límite central

Quiz: Análisis univariado

Análisis bivariado

16

Estableciendo relaciones: gráficos de puntos

17

Estableciendo relaciones: gráficos de violín y boxplots

18

Estableciendo relaciones: matrices de correlación

19

Limitantes de los coeficientes de correlación lineal

20

Estableciendo relaciones: análisis de regresión simple

21

Limitaciones del análisis de regresión simple

Quiz: Análisis bivariado

Análisis multivariado

22

Análisis de regresión múltiple

23

Visualización del análisis de regresión múltiple

24

Análisis de regresión logística

25

Paradoja de Simpson

26

¿Qué hacer cuando tengo muchas variables?

Quiz: Análisis multivariado

Conclusiones

27

Diversidad de gráficas al explorar datos

28

Continúa aprendiendo sobre EDA

You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

2 Días
21 Hrs
29 Min
47 Seg

Bonus: Teorema del límite central

15/28
Resources

Contributions 32

Questions 9

Sort by:

Want to see more contributions, questions and answers from the community?

Por si se les presenta una serie de advertencias de numpy como me paso, le dejo un código que tal vez no es el mejor pero me ayudo a eliminar la gran cantidad de advertencias.

number_samples = 1000
sample_size = 35

np.random.seed(42)

# definimos el DataFrame en blanco con su tamaño definido
samples_df = pd.DataFrame(np.random.randint(1, sample_size, size =(sample_size, number_samples)))
# Le asignamos nombres a las columnas.
col_names = []
for i in range(1, number_samples + 1):    
    col_names.append(f"sample_{i}")
samples_df.columns = col_names


for i in range(1, number_samples + 1):
    sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy()    
    sample_name = f"sample_{i}"
    samples_df[sample_name] = sex_numeric_sample

male_population_mean = samples_df.mean().mean()
print(f"El porcentaje estimado de pingüinos machos en la población es: {male_population_mean * 100:.4f}%")

Demostracion Computacional del T. de los grande numeros

Tomamos como ejemplo el lanzamiento de una dado

#calculo de la probabilidad para cada cara del dado
dice = empiricaldist.Pmf.from_seq([1,2,3,4,5,6])
dice.bar()

Valores de probabilidad para cada cara del dado en diferentes tamaños de muestras

for sample_size in (1e2, 1e3,1e4):  #100 1000 10000
    sample_size = int(sample_size)
    values = dice.sample(sample_size) # obtener valores segun tamaño de la muestra
    sample_pmf = empiricaldist.Pmf.from_seq(values) #calculo de la probabilidad para cada valor
	
		#graficas para cada tamaño de muestra
    plt.figure(figsize=(5, 5))
    sample_pmf.bar()
    plt.axhline(y=1/6, color='red', linestyle='dashed')
    plt.ylim([0,0.50])
    plt.title(f'Sample size: {sample_size}')

Demostracion del T. del Limite Central

Analizamos una variable binaria

preprocessed_penguins_df.sex.value_counts(normalize=True)

La variable sex sigue una distribucion binomial. Como es categorica, debemos convertirla en una variable numerica

sex_numeric = preprocessed_penguins_df.sex.replace(['male', 'female'], [1, 0])

Fijamos el numero de muestras a tomar y el tamaño de cada muestra, luego calculamos la media de los machos de cada muestra y a todas ellas le sacamos la media observando asi que se aproxima a la proporcion de machos dada por los datos

number_sample = 1000 #cantidad de muestras a tomar
sample_size = 35 #tamaño de la muestra

sample_df = pd.DataFrame() #dataframe donde se almacena las media de cada muestra

np.random.seed(42)

for i in range(1, number_sample + 1):
    sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy()
    sample_name = f'sample {i}'
    sample_df[sample_name] = sex_numeric_sample

male_population_mean = sample_df.mean().mean()
print(f'El porcentaje de pinguinos machos en la poblacion es de: {male_population_mean*100:.4f}%')

La distribucion binomial se convierte en este caso en una distribucion Normal como se evidencia en la grafica que sigue

sample_means_binomial = pd.DataFrame(sample_df.mean(), columns=['sample_mean'])
sns.kdeplot(data=sample_means_binomial)
plt.axvline(x=sex_numeric.mean(), color='red', linestyle='dashed')

Otra manera de verlo es ir incrementando la cantidad de muestras y observar el efecto en la proporcion de machos

sample_size_experiment = pd.DataFrame(
    [[i, sample_df.iloc[:, 0:i].mean().mean().mean()] for i in range(1, number_sample + 1)],
    columns=['sample_size', 'estimated_mean']
)

#grafica  del efecto
sns.scatterplot(
    data=sample_size_experiment,
    x='sample_size',
    y='estimated_mean'
)

plt.axhline(
    y=sex_numeric.mean(),
    color='red',
    linestyle='dashed'
)

plt.ylim([sex_numeric.mean() - 0.20, sex_numeric.mean() + 0.20])

Teorema de los grandes números

La probabilidad experimental tiende a la probabilidad teorica a medida que aumenta el numero de repeticiones del experimento. Es muy util cuando no se conoce la probabilidad teorica de un evento y tenemos la capacidad de aumentar la muestra. Mediante este teorema, al incrementar la muestra la probabilidad experimental al final se convertira en la probabilidad teorica.

Teorema del Limite Central

La media de las muestras tiende aproximadamente a una distribución normal

La suma de n variables aleatorias independientes con medias y varianzas finitas converge en distribucion a una variable aleatoria normal

El método ‘replace’ también puede recibir un diccionario 😉

sex_numeric = df_limpio.sex.replace({'male':1,'female':0})

Al ejecutar el bucle for, da este Warning (traducido al español) como resultado en jupiter lab, y estoy seguro que no es por falta de buen hardware:

DataFrame está muy fragmentado. Esto suele ser el resultado de llamar a `frame.insert` muchas veces, lo que tiene un rendimiento deficiente. Considere unir todas las columnas a la vez usando pd.concat(axis=1) en su lugar. Para obtener un marco desfragmentado, use `newframe = frame.copy()`

Se soluciona con:

from warnings import simplefilter
simplefilter(action="ignore", category=pd.errors.PerformanceWarning)

En Python, las expresiones como 1e3 o 1e2se utilizan para representar números en notación científica. En particular, 1e3 significa “1 multiplicado por 10 elevado a la potencia de 3”, que es igual a 1000. De manera similar, 1e2 significa “1 multiplicado por 10 elevado a la potencia de 2”, que es igual a 100.

Buenas 👋 Al ejecutar el código me salía un festival de warnings :/ por si a alguien le sirve, pude resolverlo usando `map` en vez de `replace` + cambiando un poco el código. * *Versión de pandas: 2.2.1* ```js sex_numeric = df_penguins['sex'].map({'male': 0, 'female': 1}).astype(int) number_samples = 1000 sample_size = 35 # número de muestras np.random.seed(42) # lista auxiliar: almacenar las muestras samples_list = [] for i in range(1, number_samples + 1): sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy() samples_list.append(pd.Series(sex_numeric_sample, name=f'sample_{i}')) # almacenar cada muestra en una serie # Concatenar todas las muestras en un nuevo df samples_df = pd.concat(samples_list, axis=1) male_proportion_mean = samples_df.mean().mean() print(f'Estimated percentage for male penguins (in total population): {male_proportion_mean * 100:.2f}%') ```

Por si les aparece el error de DataFrame is highly fragmented correr este codigo antes:

from warnings import simplefilter
simplefilter(action="ignore", category=pd.errors.PerformanceWarning)

Correlaciones entre variables Correlación Person:

*Correlación positiva Alta: En orden de correlación>5

1ro: body_mass con Flipper_length_mm
El peso de los pingüinos presenta una alta correlación con la longitud de sus alas (0,87)

2do: flipper_length_mm con bill_length_mm
La longitud de las alas de los pingüinos presenta una correlación positiva media o alta con respecto a el largo de sus picos (0,65)

3ro: body_mass con bill_length_mm
El peso de los pingüinos presenta una correlación positiva media con respecto al largo de sus picos (0,59)

Correlación positiva baja: <=5
body_mass con numeric_sex (0,42)
body_mass con year (0,022)
bill_length_mm con numeric_sex(0,34)
bill_length_mm con year (0,033)
Flipper_length_mm con numeric_sex (0,26)
Flipper_length_mm con year (0,15)
Estas variables no guardan relación entre ellas

****Correlación negativa: ****
La única variable con una correlación negativa media o alta mayor a 5, es bill_depth_mm con Flipper_length_mm.

El reto del profesor ![](https://static.platzi.com/media/user_upload/image-78c2e6e3-6b84-4679-80c0-c5f7e91da5ab.jpg) ```js sample_means_binomial= pd.DataFrame(samples_df.mean(), columns=['sample_mean']) #Distribucion de los datos sns.kdeplot( data=sample_means_binomial, label='Distribucion real', fill=True, alpha=0.1, color ='red', linewidth=0.4, ) # Distribucion teorica plt.plot( xs, ys, color='#891652', linestyle='dashed', label='Disribucion teorica', alpha=0.9) # Linea vertical en la media poblacional xs=np.linspace(sample_means_binomial.min(), sample_means_binomial.max()) ys=scipy.stats.norm(sample_means_binomial.mean(), sample_means_binomial.std()).pdf(xs) plt.axvline( x=sex_numeric.mean(), color='#FEC7B4', label='Media poblacional' ) plt.legend() plt.show() ```
  • El teorema del límite central es uno de los conceptos fundamentales de la estadística. El teorema establece que, si tomamos suficientes muestras aleatorias de una población, la distribución de las medias muestrales se aproxima a una distribución normal independientemente de la distribución de la población original, siempre que el tamaño de muestra sea suficientemente grande.

  • En otras palabras, el teorema del límite central nos dice que, a medida que aumenta el tamaño de la muestra, la distribución de las medias muestrales se acerca cada vez más a una distribución normal. Esto es importante porque muchas de las técnicas estadísticas que utilizamos asumen que las variables tienen una distribución normal, y el teorema del límite central nos permite utilizar estas técnicas incluso cuando la población original no es normal.
import seaborn as sns

# Cargamos los datos de pingüinos
penguins = sns.load_dataset('penguins')

# Seleccionamos la columna del largo del pico para la especie Adelia
adelia_bill_length = penguins[penguins['species']=='Adelie']['bill_length_mm']

import numpy as np

# Generamos 100 muestras aleatorias de tamaño 30
n_samples = 100
sample_size = 30
samples = np.random.choice(adelia_bill_length, size=(n_samples, sample_size))
means = samples.mean(axis=1)

import matplotlib.pyplot as plt

# Graficamos la distribución de las medias muestrales
plt.hist(means, bins=20)
plt.title('Distribución de las medias muestrales de Adelia (n=30)')
plt.xlabel('Largo del pico (mm)')
plt.ylabel('Frecuencia')
plt.show()

Les comparto la forma de eliminar el warning del Teorema del límite central

number_samples = 1000
sample_size = 35

np.random.seed(42)

samples_list = []
for i in range(1, number_samples + 1):
    sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy()
    samples_list.append(sex_numeric_sample)

samples_df = pd.DataFrame(np.column_stack(samples_list), columns=[f"sample_{i}" for i in range(1, number_samples + 1)])

male_population_mean = samples_df.mean().mean()
print(f"Estimated percentage of male penguins in population is: {male_population_mean * 100:.4f}%")

¿Por que el profesor no deja el codigo ya hecho en la seccion de recursos?. A veces lo que pasa la comunidad esta mal tipeado. Seria bueno que el profe sea el que pase la documentacion correcta.

Por si se les presenta un montón de warnings. ```js number_samples = 1000 sample_size=35 samples = [] np.random.seed(42) for i in range(1, number_samples + 1): sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy() samples.append(pd.Series(sex_numeric_sample, name=f"sample_{i}")) samples_df = pd.concat(samples, axis=1) male_population_mean = samples_df.mean(numeric_only=True).mean() print(f"Estimated percentage of male penguins in population is: {male_population_mean * 100:.4f}%") ```

Estimad@, si sentiste que esto no te quedó claro, yo te lo voy a dejar clarisimo.
La ley de los grandes numeros consiste en que, entre mas numeros tengas, la probabilidad de tener eventos tienden a equilibrarse.
y el teorema de limite central es que, segun la ley anterior, la distribucion de los numeros, tienden a ser central.
y esto tiene todo el sentido del mundo.
porque:
imaginate tu tienes 3 frutas.

  1. Manzana.
  2. Pera.
  3. Coco.
    se distribuyen asi.
    1 = 40 unidades.
    2 = 15 unidades.
    3 = 2 unidades.

si las metes en una caja.
cual es la probabilidad de sacar Manzana, Pera y coco(respectivamente)
obviamente Manzana es la mayor probabilidad.
entonces, la ley de los numeros grandes establece que:
entre mas unidades(muestras) tengas, esta probabilidad tiende a equipararse(equilibrarse) osea que, ya sacar una manzana no es una gran probabilidad.

ahora.
el teorema de limite central acompaña a esta teoria(complementa), diciendo que:
entonces, cuando se aplica la ley anterior, la distribucion de los numeros tienden a ser centrales.
es decir, van a ser limites centrales, limite central es que busca una distribucion normal.
(**SI NO LO ENTIENDES AQUI, TE RECOMIENDO QUE COPIES Y PEGUES ESTA INFORMACION EN CHAT-GPT **y le hagas preguntas sobre esto.)

el codigo tiene mayusculas: sex_numeric = processed_penguins_df.sex.replace([‘Male’, ‘Female’], [1, 0])

15. Bonus: Teorema del límite central

Ley de los grandes números

“La probabilidad experimental tiende a la probabilidad teórica a medida que aumenta el número de repeticiones del experimento”

Teorema del Límite Central

“La media de las muestras tiende aproximadamente a una distribución normal.”

“La suma de n variables aleatorias independientes con medias y varianzas finitas converge en una distribución a una variable aleatoria con distribución normal.”

Este muestreo es un muestreo aleatorio con reemplazo, ya que cada vez que saco 35 pingüinos de la muestra de los 333 pingüinos debo volver a meter los pingüinos que saque por decirlo así de la bolsa y hacer el ejercicio 999 veces mas.

In the Python string formatting syntax, .4f is used to specify that the float value should be formatted with four decimal places after the decimal point.

In the context of the given code, {male_population_mean * 100:.4f} means that the float value of male_population_mean * 100 will be formatted to display up to four decimal places after the decimal point.

Me fui a buscar un poco más de información sobre el Teorema del Límite Central, y encontré este video que me gustó bastante. Simple, con ejemplos en código, con algo de teoría. <https://youtu.be/s6w-Z9SyAlA?si=VxoS0CHANX3Z-yPI>
#### **DEEPNOTE**  #### **1. CREAR Y VISUALIZAR LA FUNCIÓN DE MASA DE PROBABILIDAD (PMF) DE UN DADO JUSTO** **Código:** dice = empiricaldist.Pmf.from\_seq(\[1, 2, 3, 4, 5, 6]) dice.bar() **Explicación:** 1. empiricaldist.Pmf.from\_seq(\[1, 2, 3, 4, 5, 6]): Crea una función de masa de probabilidad (PMF) a partir de una secuencia de números que representan los resultados de lanzar un dado justo de seis caras. 2. dice.bar(): Grafica un gráfico de barras para visualizar la PMF, mostrando que todos los seis resultados tienen igual probabilidad. **Salida:** Un gráfico de barras que muestra probabilidades uniformes para los números del 1 al 6, cada uno con una probabilidad de aproximadamente 0.1667 (1/6). #### **2. MUESTREO DE LA PMF PARA DIFERENTES TAMAÑOS DE MUESTRA** **Código:** for sample\_size in (1e2, 1e3, 1e4):     sample\_size = int(sample\_size)     values = dice.sample(sample\_size)     print(values) **Explicación:** 1. for sample\_size in (1e2, 1e3, 1e4): Itera sobre tres tamaños de muestra: 100, 1000 y 10,000. 2. sample\_size = int(sample\_size): Convierte el tamaño de muestra de un número de punto flotante a un entero. 3. values = dice.sample(sample\_size): Genera una muestra aleatoria de tamaño sample\_size de la PMF del dado. 4. print(values): Imprime los valores muestreados para cada tamaño de muestra. **Salida:** Tres arreglos impresos con los valores muestreados. Cada arreglo corresponde a un tamaño de muestra y contiene números aleatorios entre 1 y 6 (inclusive), muestreados de acuerdo con la PMF. **3. VISUALIZAR LA DISTRIBUCIÓN MUESTRAL PARA DIFERENTES TAMAÑOS DE MUESTRA** **Código:** for sample\_size in (1e2, 1e3, 1e4):     sample\_size = int(sample\_size)     values = dice.sample(sample\_size)     sample\_pmf = empiricaldist.Pmf.from\_seq(values)     plt.figure(figsize=(5, 5))     sample\_pmf.bar()     plt.axhline(y=1/6, color='red', linestyle='dashed')     plt.ylim(\[0, 0.5])     plt.title(f"Sample size: {sample\_size}") **Explicación:** 1. for sample\_size in (1e2, 1e3, 1e4): Itera sobre tres tamaños de muestra: 100, 1000 y 10,000. 2. sample\_size = int(sample\_size): Convierte el tamaño de muestra a un entero. 3. values = dice.sample(sample\_size): Genera una muestra aleatoria de tamaño sample\_size de la PMF del dado. 4. sample\_pmf = empiricaldist.Pmf.from\_seq(values): Crea una nueva PMF a partir de los valores muestreados. 5. plt.figure(figsize=(5, 5)): Configura el tamaño de la figura para el gráfico. 6. sample\_pmf.bar(): Grafica un gráfico de barras de la PMF de la muestra. 7. plt.axhline(y=1/6, color='red', linestyle='dashed'): Agrega una línea horizontal punteada en la probabilidad teórica de 1/6 para comparación. 8. plt.ylim(\[0, 0.5]): Establece los límites del eje y para una mejor visualización. 9. plt.title(f"Sample size: {sample\_size}"): Agrega un título al gráfico indicando el tamaño de la muestra. **Salida:** Tres gráficos de barras que muestran la distribución de los valores muestreados para cada tamaño de muestra: * **Tamaño de muestra: 100**: Mayor variabilidad respecto a la distribución uniforme teórica. * **Tamaño de muestra: 1000**: Menor variabilidad, más cercana a la distribución teórica. * **Tamaño de muestra: 10,000**: La distribución se ajusta estrechamente a las probabilidades teóricas de 1/6 para cada resultado. #### **4. GRÁFICO DE BARRAS DE LA DISTRIBUCIÓN DE SEXOS EN EL DATASET DE PINGÜINOS** **Código:** processed\_penguins\_df.sex.value\_counts(normalize=True).plot(kind='bar') **Explicación:** 1. processed\_penguins\_df.sex.value\_counts(normalize=True): Calcula la proporción de pingüinos machos y hembras en el dataset al normalizar los conteos. 2. .plot(kind='bar'): Genera un gráfico de barras para visualizar las proporciones normalizadas. **Salida:** Un gráfico de barras que muestra proporciones similares para machos y hembras. #### **5. CODIFICACIÓN NUMÉRICA DE SEXOS Y MUESTREO** **Código:** processed\_penguins\_df.sex.value\_counts(normalize=True) sex\_numeric = processed\_penguins\_df.sex.replace(\['male', 'female'], \[1, 0]) number\_samples = 1000 sample\_size = 39 samples\_df = pd.DataFrame() np.random.seed(42) for i in range(1, number\_samples + 1):     sex\_numeric\_sample = sex\_numeric.sample(sample\_size, replace=True).to\_numpy()     samples\_df\[f'sample\_{i}'] = sex\_numeric\_sample male\_population\_mean = samples\_df.mean().mean() print(f"Estimated percentage of male penguins in population is: {male\_population\_mean \* 100:.4f}%") **Explicación:** 1. Calcula las proporciones normalizadas de machos y hembras. 2. Codifica 'male' como 1 y 'female' como 0. 3. Define 1000 muestras y un tamaño de muestra de 39. 4. Usa un bucle para generar muestras aleatorias y calcular su media. **Salida:** El porcentaje estimado de pingüinos machos es aproximadamente **50.1829%**. #### **6. DISTRIBUCIÓN DE MEDIAS MUESTRALES** **Código:** sample\_means\_binomial = pd.DataFrame(samples\_df.mean(), columns=\['sample\_mean']) sns.kdeplot(data=sample\_means\_binomial) plt.axvline(x=sex\_numeric.mean(), color='red', linestyle='dashed') **Explicación:** 1. Calcula las medias de las muestras. 2. Genera un gráfico KDE de las medias. 3. Agrega una línea vertical indicando la media teórica de la población. **Salida:** Gráfico KDE mostrando la distribución de las medias muestrales y la línea roja que indica la media teórica. #### **7. VISUALIZACIÓN DE LA CONVERGENCIA DE LA MEDIA CON EL TAMAÑO DE LA MUESTRA** **Código:** sample\_size\_experiment = pd.DataFrame(     \[\[i, samples\_df.iloc\[:, :i].mean().mean()] for i in range(1, number\_samples + 1)],     columns=\['sample\_size', 'estimated\_mean'] ) sns.scatterplot(     data=sample\_size\_experiment,     x='sample\_size',     y='estimated\_mean' ) plt.axhline(     y=sex\_numeric.mean(),     color='red',     linestyle='dashed' ) plt.ylim(\[sex\_numeric.mean() - 0.20, sex\_numeric.mean() + 0.20]) **Explicación:** 1. Crea un DataFrame para rastrear la convergencia de medias. 2. Genera un scatterplot de tamaño de muestra versus media estimada. 3. Agrega una línea horizontal indicando la media teórica. **Salida:** Scatterplot que muestra cómo la media muestral converge a la media teórica a medida que aumenta el tamaño de la muestra.
### **LEY DE LOS GRANDES NÚMEROS Y TEOREMA DEL LÍMITE CENTRAL** #### **1. LA LEY DE LOS GRANDES NÚMEROS** **¿Qué significa?** Imagina que tienes un dado con seis caras, todas con la misma probabilidad de caer, es decir, un sexto (1/6) para cada cara. Esta probabilidad se cumple en teoría, pero, ¿qué sucede en la práctica? **Ejemplo: Lanzamientos del dado** * **Con 100 lanzamientos:** Las frecuencias de cada cara pueden variar bastante. Por ejemplo, el número 2 puede aparecer más veces que el resto, mientras que el 3 puede aparecer menos. Aunque parezca que el dado no es justo, sigue siéndolo. * **Con más lanzamientos (1,000, 10,000, 100,000):** A medida que aumentamos el número de lanzamientos, las frecuencias de cada cara se acercan más a la probabilidad teórica de un sexto. Esto es **la Ley de los Grandes Números**: * Cuando el tamaño de la muestra aumenta, los resultados observados tienden a reflejar las probabilidades teóricas. * Este principio se aplica en múltiples contextos, permitiendo estimar probabilidades con precisión al incrementar la cantidad de datos. #### **2. EL TEOREMA DEL LÍMITE CENTRAL** **¿Por qué es importante?** Este teorema es una de las bases fundamentales de la estadística. Sin él, muchas herramientas y métodos que utilizamos hoy no existirían. **Definición básica:** La media de las muestras tiende a seguir una **distribución normal**, incluso si los datos originales no lo hacen. **Definición técnica:** La suma de *n* variables aleatorias independientes (con medias y varianzas finitas) converge hacia una distribución normal a medida que *n* crece. **Ejemplo práctico:** Imagina que tomamos pequeñas muestras de una población y calculamos sus medias. * Con un número suficiente de muestras, esas medias se distribuyen de forma aproximadamente normal. * Esto permite analizar datos, calcular probabilidades y hacer predicciones basadas en patrones observables.
Yo había nombrado mi dataset de otra forma, pero aquí dejo mi aporte # Initializing samples as an empty listsamples = \[] np.random.seed(42)for i in range(1, number\_samples + 1):    sex\_num\_sample = sex\_num.sample(sample\_size, replace=True).to\_numpy()    samples.append(pd.Series(sex\_num\_sample, name=f"sample\_{i}")) \# Concatenate the samples along the columns into a DataFramesamples\_df = pd.concat(samples, axis=1) \# Ensuring that column headers 'male' and 'female' exist for meaningful analysissamples\_df.columns = \[f"sample\_{i}" for i in range(1, number\_samples + 1)] male\_population\_mean = sex\_num.mean()female\_population\_mean = 1 - male\_population\_mean  # female mean is complementaryprint(f"Estimated percentage of male penguins: {male\_population\_mean \* 100:.4f}%")print(f"Estimated percentage of female penguins: {female\_population\_mean \* 100:.4f}%")
```js # Definición de variables number_samples = 1000 # número total de muestras sample_size = 35 # número de individuos en cada muestra # Lista para almacenar cada muestra como un array samples = [] # Fijamos la semilla para reproducibilidad np.random.seed(42) # Generamos las muestras for _ in range(number_samples): sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy() samples.append(sex_numeric_sample) # Crear el DataFrame con todas las muestras de una sola vez sample_df = pd.DataFrame(samples).T # Transponemos para tener cada muestra en una columna # Calcular el promedio de la proporción de machos en la población male_population_mean = sample_df.mean().mean() print(f"El % estimado de machos respecto a toda la población es de: {male_population_mean * 100:.4f}%") ```# Definición de variablesnumber\_samples = 1000  # número total de muestrassample\_size = 35       # número de individuos en cada muestra \# Lista para almacenar cada muestra como un arraysamples = \[] \# Fijamos la semilla para reproducibilidadnp.random.seed(42) \# Generamos las muestrasfor \_ in range(number\_samples):    sex\_numeric\_sample = sex\_numeric.sample(sample\_size, replace=True).to\_numpy()    samples.append(sex\_numeric\_sample) \# Crear el DataFrame con todas las muestras de una sola vezsample\_df = pd.DataFrame(samples).T  # Transponemos para tener cada muestra en una columna \# Calcular el promedio de la proporción de machos en la poblaciónmale\_population\_mean = sample\_df.mean().mean()print(f"El % estimado de machos respecto a toda la población es de: {male\_population\_mean \* 100:.4f}%")
Hay que hacer un cambio en el código usado para demostrar el teorema de límite central, así me quedó: number\_samples = 1000sample\_size=35 samples\_df = pd.DataFrame()# Create an empty list to store all samplessamples\_list = \[] np.random.seed(42)for i in range(1, number\_samples + 1):    sex\_numeric\_sample = sex\_numeric.sample(sample\_size, replace=True).to\_numpy()    samples\_list.append(sex\_numeric\_sample)  # Append each sample to the list    \# Convert the list of samples to a DataFrame all at oncesamples\_df = pd.DataFrame(samples\_list).T  # Transpose to match the original structure# Rename the columns for claritysamples\_df.columns = \[f"sample\_{i}" for i in range(1, number\_samples + 1)] male\_population\_mean = samples\_df.mean().mean()print(f"Estimated percentage of male penguins in population is: {male\_population\_mean \* 100:.4f}%")
Entonces podemos decir que "La ley de los grandes números" está basada en la perspectiva "Frecuentista" ...
Creo que es indispensable entender que las muestras siempre son aleatoria, es decir que si tomasemos siempre los mismo 10 datos, evidentemente no obtendriamos un resultado natural
Yo use la funcion distplot (que esta deprecada y sera removida de versiones siguientes) y nos entrega la comparacion de la funcion de densidad normal vs el histograma: `sns.histplot(data=df_samples.mean())` `plt.axvline(x=sex_numeric.mean(), color='red')` `plt.ylabel('Valor real de la proporcion de Males')` `plt.title('Distribucion de las medias de las 1000 samples de 35 valores cada sample')` `plt.show()` ![](https://static.platzi.com/media/user_upload/image-640142bd-07b2-4572-8a54-6161173704eb.jpg)
number_samples = 10000
sample_size = 50

samples_list = []

np.random.seed(42)
for i in range(1, number_samples + 1):
    sex_numeric_sample = sex_numeric.sample(sample_size, replace=True).to_numpy()
    samples_list.append(sex_numeric_sample)

samples_df = pd.DataFrame(np.column_stack(samples_list), 
                          columns=[f"sample_{i}" for i in range(1, number_samples + 1)])

# Plot kernel density of sample means
sample_means_binomial = pd.DataFrame(samples_df.mean(), columns=['sample_mean'])

# Set a wider figure size
plt.figure(figsize=(12, 6))

sns.kdeplot(data=sample_means_binomial['sample_mean'], label='Sample Means')

# Calculate statistics for the sample means
sample_means_stats = {
    'mean': sample_means_binomial['sample_mean'].mean(),
    'std' : sample_means_binomial['sample_mean'].std(),
    'min' : sample_means_binomial['sample_mean'].min(),
    'max' : sample_means_binomial['sample_mean'].max()
}

# Generate x values for the theoretical normal distribution
xs = np.linspace(sample_means_stats['min'], sample_means_stats['max'], 50)

# Calculate the PDF for the theoretical normal distribution
ys = scipy.stats.norm(sample_means_stats['mean'], sample_means_stats['std']).pdf(xs)

# Plot the theoretical normal distribution
plt.plot(xs, ys, color='black', linestyle='dashed', label='Theoretical Normal Distribution')

# Highlight the mean of sample means
plt.axvline(x=sample_means_stats['mean'], color='red', linestyle='dashed', label='Mean of Sample Means')

plt.title('Kernel Density Plot and Theoretical Normal Distribution of Sample Means')
plt.legend()
plt.show()

Qué curioso que la grafica final se asemeje demasiado a las resultantes al calcular la funcion de transferencia en teoria de control clásico mediante la transformada de LaPlace

Este video me ayudo a entender mejor el concepto: https://www.youtube.com/watch?v=o2afi9BKRIM&ab_channel=Estadísticaútil

Aquí aplique el Teorema del límite central a la variable body_mass_g y estos fueron los resultados(el codigo esta en mi deepnote):
Esto también funciona para estimar (o inferir) otros estadísticos (standard deviation, median, mode, etc).
Estimado de la media = 4198.408571428571
Media real del conjunto = 4207.057057057057