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

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

18 Días
18 Hrs
47 Min
22 Seg

Ejercicio de obtención de medidas de dispersión

12/28
Recursos

Aportes 61

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Es interesante ver la distribución del conjunto de datos de las tres especies. 🤔

Ciertamente, parece bimodal, aunque posiblemente al normalizar la data, encontraremos algún factor influyente que cambie este panorama 📊


var_flipper_len = processed_penguins_df['flipper_length_mm']

g=sns.histplot(
    data=processed_penguins_df,
    x='flipper_length_mm',
    binwidth=1,
    hue='species',
    alpha=.5
)
g.set_title('Penguins Flipper Length Distribution', y=1.03)

# Mean(Red)
plt.axvline(
    x =var_flipper_len.mean(),
    linestyle="dashed",
    color="r",
    linewidth=2
)

# Median(Green)
plt.axvline(
    x=var_flipper_len.median(),
    linestyle="dashed",
    color="g",
    linewidth=2
)

# Q_75(Black)
plt.axvline(
    x=var_flipper_len.quantile(0.75),
    linestyle="dashed",
    color="k",
    linewidth=2
)

# Q_25(Black)
plt.axvline(
    x=var_flipper_len.quantile(0.25),
    linestyle="dashed",
    color="k",
    linewidth=2
)

plt.text(184.7,17.5, 'Q(25%)', fontsize=12)
plt.text(192,17.5, 'median', fontsize=12, color='g')
plt.text(201.5,17.5, 'mean', fontsize=12, color='r')
plt.text(213.5,17.5, 'Q(75%)', fontsize=12)

plt.show()

En este caso, la distribución pareciera bimodal pero se debe a que las 3 especies tienen distribuciones distintas, sin embargo, cada especie pareciera tener una distribución normal.
Las lineas rojas y azules marcan la media y desviación estandar de toda la población:

Aca visualizamos la distribucion de las distintas caracteristicas por especie

numeric_columns = penguins_df.select_dtypes(include=np.number).columns

fig,ax = plt.subplots(1,len(numeric_columns), figsize=(15,5))

for i in range(len(numeric_columns)):
    sns.histplot( 
        ax=ax[i],
        data=penguins_df,
        x=numeric_columns[i],
        multiple='stack',
        hue='species',
        bins=15,
        palette=penguin_color,
        kde=True,
        )

Aca visualizamos una caracteristica en especifico con su media respectiva, cuantiles y ya separadas las especies

species = penguins_df.species.unique()

adelie_df = penguins_df.query("species == 'Adelie'")
gentoo_df = penguins_df.query("species == 'Gentoo'")
chinstrap_df = penguins_df.query("species == 'Chinstrap'")

list = [adelie_df,gentoo_df,chinstrap_df]
fig,ax = plt.subplots(1,len(list), figsize=(15,5), sharey=True)

for i in range(len(list)):
    sns.histplot( 
        ax=ax[i],
        data=list[i],
        x='flipper_length_mm',
        multiple='layer',
        hue='species',
        bins=15,
        kde=True,
        palette=penguin_color,
        )

    ax[i].axvline(
        x=list[i]['flipper_length_mm'].mean(),
        color='red'
        )

    ax[i].axvline(
        x=list[i]['flipper_length_mm'].quantile(.25),
        color='blue'
        )

    ax[i].axvline(
        x=list[i]['flipper_length_mm'].quantile(.75),
        color='blue'
        )```

¿Cuál es el valor Freedman-Diaconis?

Después de la función la declaramos.
Para Flipper_length_mm: 3.3 👇

Las gráficas boxenplot nos ayudan a identificar un poco mejor la distribución de nuestros datos sin necesidad de hacer un histplot. Es tan versatil que podemos ajustar la cantidad de quantiles que queremos relfejar.
Aunque es más útil cuando hay mayor cantidad de datos puede influir en una mejor interpretación:

sns.boxenplot(
    data=preprocess_penguins_df,
    x="flipper_length_mm",
    y="species",
    palette=penguin_color,
    k_depth=4
);

Un plus sería analizarlos por sexo:

El profesor en el minuto 5:20 indica que el valor del cuartil 50% es igual al valor de la media, pero creo que se refiere a la mediana. Porque esos valores corresponde a la mediana.

Para poder hacer una comparación rápida entre las variables de los pinguineins

species = penguins_df.species.unique()

adelie_df = penguins_df.query("species == 'Adelie'")
gentoo_df = penguins_df.query("species == 'Gentoo'")
chinstrap_df = penguins_df.query("species == 'Chinstrap'")

list = [adelie_df,gentoo_df,chinstrap_df]
numeric_columns = penguins_df.select_dtypes(include=np.number).columns
fig,ax = plt.subplots(len(numeric_columns),len(list),sharey=True, figsize=(15,12))

for j in range(len(numeric_columns)):
    for i in range(len(list)):
        sns.histplot( 
            ax=ax[j][i],
            data=list[i],
            x=numeric_columns[j],
            multiple='stack',
            hue='species',
            bins=15,
            kde=True,
            palette=penguin_color,
            )
        

        ax[j][i].set_ylabel(f'{numeric_columns[j]}')
        ax[j][i].set_xlabel(f'{species[i]}')

        ax[j][i].get_legend().remove()

Menos codigo mas accion.

sns.histplot(
    data=processed_penguins_df,
    x='flipper_length_mm'
)
x_stats = [
    [processed_penguins_df.flipper_length_mm.mean(),'r',2],
    [processed_penguins_df.flipper_length_mm.median(),'g',2],
    [processed_penguins_df.flipper_length_mm.mode().max(),'y',2],
    [processed_penguins_df.flipper_length_mm.quantile(0.75),'k',2],
    [processed_penguins_df.flipper_length_mm.quantile(0.25),'k',1]
    ]
 
[plt.axvline(
    x=value[0], 
    color=value[1],
    linestyle='dashed',
    linewidth=value[2]
    ) for value in x_stats]
    
heigth = 75
plt.text(processed_penguins_df.flipper_length_mm.quantile(0.25)+ 0.25,heigth, 'Q(25%)', fontsize=12)
plt.text(processed_penguins_df.flipper_length_mm.mode().max() + 0.25,heigth-3, 'mode', fontsize=12, color='y')
plt.text(processed_penguins_df.flipper_length_mm.median() + 0.25,heigth-6, 'median', fontsize=12, color='g')
plt.text(processed_penguins_df.flipper_length_mm.mean()+ 0.25,heigth-9, 'mean', fontsize=12, color='r')
plt.text(processed_penguins_df.flipper_length_mm.quantile(0.75)+0.25,heigth, 'Q(75%)', fontsize=12)

Con la longitud del pico pingüinesco:

*La Isla Biscoe es la más densamente poblada: En ella, los pingüinos suelen tener una longitud del pico promedio, también es donde podemos encontrar la mayor cantidad de pingüinos con el pico más grande, aunque no es una cantidad significativa

Determinación el tamaño de binwidth del histograma mediante la regla de Freedman-Diaconis

Los histogramas se utilizan para estimar la distribución de probabilidad de una variable aleatoria continua. Se utilizan con frecuencia como punto de partida del análisis exploratorio de datos y proporcionan información sobre la forma y la variabilidad de los datos en cuestión. Uno de los desafíos en la construcción de histogramas es seleccionar el número óptimo de contenedores (o, análogamente, el ancho de cada contenedor). Para ayudar a determinar un ancho de intervalo razonable, podemos aprovechar la regla de Freedman-Diaconis, que fue diseñada para minimizar la diferencia entre el área bajo la distribución de probabilidad empírica y el área bajo la distribución de probabilidad teórica.

Formalmente, la regla toma como entrada el rango intercuartílico IQR(x) y el número de observaciones n en el conjunto de datos empíricos, y devuelve una estimación del ancho del intervalo. La regla se puede expresar como:

$$Bin~width = 2 \frac{IQR(x)}{\sqrt{n}}$$

sns.histplot(data=penguins_df_final, x="flipper_length_mm", kde=True, binwidth=freedman_diaconis_bindwidth(penguins_df_final.bill_length_mm));
plt.axvline(x=penguins_df_final.flipper_length_mm.mean(), color = 'red', linestyle='dashed', linewidth=2); 

Para complementar el ultimo comentario de la clase, les comparto el Anscombe’s Quartet:

Never trust summary statistics alone; always visualize your data

Aquí mi histograma con bins=3 y haciendo hue=‘species’:

sns.histplot(
    data = preprocess_penguins_df,
    x='flipper_length_mm',
    hue='species',
    palette=penguin_color,
    binwidth=3
)

plt.axvline(
    x=preprocess_penguins_df.flipper_length_mm.mean(),
    color = 'red',
    linestyle = 'dashed',
    linewidth=3
)
plt.axvline(
    x=preprocess_penguins_df.flipper_length_mm.median(),
    color = 'green',
    linestyle = 'dashed',
    linewidth=3
)

plt.text(preprocess_penguins_df.flipper_length_mm.median(),30, 'median', fontsize=12, color='g')
plt.text(preprocess_penguins_df.flipper_length_mm.mean(), 30, 'mean', fontsize=12, color='r')

plt.show()```

Medidas de Dispersion Notebook

  • max() arroja los valores maximos de las variables del dataset. Utiliza el parametro numeric_only para obtener el maximo solo de las variables numericas
dataFrame.max(numeric_only=True)
  • min() arroja los valores minimos de las variables del dataset
dataFrame.min(numeric_only=True)
  • Calculo del rango intercuartil mostrado en una tabla
(
    dataFrame
    .quantile(q=[0.75,0.50,0.25])
    .transpose()
    .rename_axis('variable')
    .reset_index()
    .assign(
        iqr=lambda df: df[0.75] - df[0.25]
    )
)
  • Histograma de una variable del dataset
#histograma
sns.histplot(
    data=preprocessed_penguins_df,
    x='flipper_length_mm'
)

#trazar la media en la grafica
plt.axvline(
    x=preprocessed_penguins_df.flipper_length_mm.mean(),
    color='red',
    linestyle='dashed',
    linewidth=2
)
  • Diagrama de caja de una variable del dataset
sns.boxplot(
    data=preprocessed_penguins_df,
    x='flipper_length_mm',
)
  • Funcion Freedman Diaconis. Permite calcular el bin mas adecuado basados en el rango intercuartil

La proporción de los pinguinos por isla:

Luego, hice un hist para comparar la masa en cada isla.
Al parecer también muchas comparaciones serán bimodales ya que serán pinguinos de islas distintas, pero al parecer los pinguinos en la isla biscoe son más gorditos

fig = px.histogram(processed_penguins_df, x="flipper_length_mm",
                   marginal="box", color='species', opacity=0.8,
                   hover_data=processed_penguins_df.columns)
fig.show()
fig = px.box(processed_penguins_df, y="flipper_length_mm", color='species', points="all")
fig.show()

Comparto un histograma sobre la variable bill_length_mm con las medidas de tendencia central .

El ancho de banda de Freedman-Diaconis (Freedman-Diaconis bin width) es una regla de referencia para determinar el tamaño óptimo de los intervalos (bins) en un histograma. Esta regla equilibra la necesidad de suficiente resolución en el histograma para ver los detalles en la distribución de datos, sin sobreajustar el ruido.
También si corregimos el boxplot por especie da lo siguiente: ![](https://static.platzi.com/media/user_upload/image-5891b30b-3977-4def-8254-1ec6cc2bd71f.jpg) ```js sns.boxplot( data=penguins_df, x='flipper_length_mm', y='species', palette=penguin_color ) ```sns.boxplot(    data=penguins\_df,    x='flipper\_length\_mm',    y='species',    palette=penguin\_color)

Se nota que hay que llegar aquí con bases mas sólidas… No tengo interiorizado el funcionamiento de funciones lambda.

Minuto 7:56 si les aparece key 0.25 error, aqui esta la solucion

result = (
    data
    .quantile(q=[0.75, 0.50, 0.20])
    .transpose()
    .rename_axis("variable")
    .reset_index()
)

if 0.25 in result.columns and 0.75 in result.columns:
    result = result.assign(iqr=lambda df: df[0.75] - df[0.25])

result

Con la funcion describe() de pandas tambien podemos tener las medidas de dispersion por lo que use estos datos para ya graficarlos en el histograma 😉

sns.histplot(
        data=df,
        x='flipper_length_mm',
        bins=6)

colors = ['red', 'blue', 'green', 'orange', 'yellow', 'brown']
df_metrics = df.describe()[['flipper_length_mm']].transpose()

i = 0
for metric in df_metrics.columns:
    if metric != 'std' and metric != 'count': 
        plt.axvline(x=df_metrics[metric].values, 
                    color=colors[i], 
                    label=metric, 
                    linestyle='dashed', 
                    linewidth = 2)
        i = i+1
    else: pass

plt.legend()

desviación estándar:
1σ Incluye el 68% de los datos
2σ Incluye el 95% de los datos
3σ Incluye el 99.7% de los datos

Otra forma de hacer la tabla usando la función apply:

Para ver de forma gráfica la media de cada especie hice lo siguiente:

ys = processed_penguins_df.groupby(['species']).flipper_length_mm.mean()

sns.histplot(processed_penguins_df,
             x='flipper_length_mm',
             binwidth=1,
             hue='species',
             alpha=.5
             )
plt.axvline(
    x=ys[0],
    linestyle="dashed",
    color="blue",
    linewidth=2
)
plt.axvline(
    x=ys[1],
    linestyle="dashed",
    color="green",
    linewidth=2
)
plt.axvline(
    x=ys[2],
    linestyle="dashed",
    color="orange",
    linewidth=2
)

plt.show()

Para ver de forma gráfica la media de cada especie hice lo siguiente:

ys = processed_penguins_df.groupby(['species']).flipper_length_mm.mean()

sns.histplot(processed_penguins_df,
             x='flipper_length_mm',
             binwidth=1,
             hue='species',
             alpha=.5
             )
plt.axvline(
    x=ys[0],
    linestyle="dashed",
    color="blue",
    linewidth=2
)
plt.axvline(
    x=ys[1],
    linestyle="dashed",
    color="green",
    linewidth=2
)
plt.axvline(
    x=ys[2],
    linestyle="dashed",
    color="orange",
    linewidth=2
)

plt.show()
Implementando la función `freedman` lo hice así (espero que sea así): ![](https://static.platzi.com/media/user_upload/image-b6250a07-a47c-4275-a54c-f84e17d5ab6c.jpg) Me arrojó un resultado grafico ![](https://static.platzi.com/media/user_upload/image-0fdfdbd5-7572-4fe7-983d-bf599e2e7cdc.jpg) Espero que sea correcto. Si desean visitar mi repositorio de Git Hub de este curso, aquí lo dejo: <https://github.com/DensLopez/Analisis_Exploratorio>
```python # Creacion de ejes: 2 filas y 1 columna fig, ax = plt.subplots(2,1,figsize=(6, 6), sharex=True) # Configuracion para texto bbox_props = dict( boxstyle="round,pad=0.3", edgecolor="none", facecolor="black", alpha=0.7 ) # Grafico de distribucion sns.histplot( data=preproces_penguins_df, x='flipper_length_mm', ax=ax[0] ) # Media linea ax[0].axvline( x=preproces_penguins_df.flipper_length_mm.mean(), color='red', linestyle='dashed', linewidth=2, label='mediana' ) ax[0].text( preproces_penguins_df.flipper_length_mm.mean(), 70, 'Media', color='w', verticalalignment='bottom', bbox=bbox_props) # Q25 linea ax[0].axvline( x=preproces_penguins_df.flipper_length_mm.quantile(0.25), color='green', linestyle='dashed', linewidth=2, label='mediana' ) ax[0].text( preproces_penguins_df.flipper_length_mm.quantile(0.25), 70, 'Q25', color='w', verticalalignment='bottom', bbox=bbox_props) # Q75 linea ax[0].axvline( x=preproces_penguins_df.flipper_length_mm.quantile(0.75), color='green', linestyle='dashed', linewidth=2, label='mediana' ) ax[0].text( preproces_penguins_df.flipper_length_mm.quantile(0.75), 70, 'Q75', color='w', verticalalignment='bottom', bbox=bbox_props) # Grafico de cajas sns.boxplot( data=preproces_penguins_df, x='flipper_length_mm', ax=ax[1] ) # Quitar todo del gráfico de cajas excepto el gráfico ax[1].set_yticks([]) # Quitar los ticks del eje y ax[1].set_ylabel('') # Quitar la etiqueta del eje y ax[0].set_xlabel('') # Quitar la etiqueta del eje x ax[1].xaxis.set_ticks([]) # Quitar los ticks del eje x ax[1].xaxis.set_ticklabels([])# Quitar las etiquetas de los ticks del eje x ax[1].grid(False) # Quitar la cuadrícula # Quitar el recuadro (marco) alrededor del gráfico ax[1].spines['top'].set_visible(False) ax[1].spines['right'].set_visible(False) ax[1].spines['left'].set_visible(False) ax[1].spines['bottom'].set_visible(False) plt.show() ```*#* Creacion de ejes: 2 filas y 1 columnafig, ax = plt.subplots(2,1,figsize=(6, 6), sharex=True) *#* Configuracion para textobbox\_props = dict( boxstyle="round,pad=0.3", edgecolor="none", facecolor="black", alpha=0.7) *#* Grafico de distribucionsns.histplot( data=preproces\_penguins\_df, x='flipper\_length\_mm', ax=ax\[0]) *#* Media lineaax\[0].axvline( x=preproces\_penguins\_df.flipper\_length\_mm.mean(), color='red', linestyle='dashed', linewidth=2, label='mediana')ax\[0].text( preproces\_penguins\_df.flipper\_length\_mm.mean(), 70, 'Media', color='w', verticalalignment='bottom', bbox=bbox\_props) *#* Q25 lineaax\[0].axvline( x=preproces\_penguins\_df.flipper\_length\_mm.quantile(0.25), color='green', linestyle='dashed', linewidth=2, label='mediana')ax\[0].text( preproces\_penguins\_df.flipper\_length\_mm.quantile(0.25), 70, 'Q25', color='w', verticalalignment='bottom', bbox=bbox\_props) *#* Q75 lineaax\[0].axvline( x=preproces\_penguins\_df.flipper\_length\_mm.quantile(0.75), color='green', linestyle='dashed', linewidth=2, label='mediana')ax\[0].text( preproces\_penguins\_df.flipper\_length\_mm.quantile(0.75), 70, 'Q75', color='w', verticalalignment='bottom', bbox=bbox\_props) *#* Grafico de cajassns.boxplot( data=preproces\_penguins\_df, x='flipper\_length\_mm', ax=ax\[1]) *#* Quitar todo del gráfico de cajas excepto el gráficoax\[1].set\_yticks(\[]) *#* Quitar los ticks del eje yax\[1].set\_ylabel('') *#* Quitar la etiqueta del eje yax\[0].set\_xlabel('') *#* Quitar la etiqueta del eje xax\[1].xaxis.set\_ticks(\[]) *#* Quitar los ticks del eje xax\[1].xaxis.set\_ticklabels(\[])*#* Quitar las etiquetas de los ticks del eje xax\[1].grid(False) *#* Quitar la cuadrícula *#* Quitar el recuadro (marco) alrededor del gráficoax\[1].spines\['top'].set\_visible(False)ax\[1].spines\['right'].set\_visible(False)ax\[1].spines\['left'].set\_visible(False)ax\[1].spines\['bottom'].set\_visible(False) plt.show() ![](https://static.platzi.com/media/user_upload/f2436342-65b2-43d5-a73e-512fca3794af-1f39d3da-d10b-4659-8b10-b0e2c3343293.jpg)
![](https://static.platzi.com/media/user_upload/image-8870ce61-1059-43f4-b20b-fdb374a0600b.jpg) `sns.histplot( data=processed_penguins_df, x='flipper_length_mm', hue='species', # Utiliza la columna 'species' para diferenciar colores palette=penguin_color # Aplica la paleta de colores personalizada)` `# Obtener valores para las líneas verticalesmedian_value = processed_penguins_df.flipper_length_mm.median()mode_value = processed_penguins_df.flipper_length_mm.mode().values[0]quantile_25_value = processed_penguins_df.flipper_length_mm.quantile(0.25)quantile_75_value = processed_penguins_df.flipper_length_mm.quantile(0.75)` `# Agregar líneas verticales y etiquetasplt.axvline( x=median_value, color='blue', linestyle='dashed', linewidth=2)plt.text(median_value, plt.gca().get_ylim()[1] * 0.9, 'Mediana', color='blue', rotation=0)` `plt.axvline( x=mode_value, color='black', linestyle='dashed', linewidth=4)plt.text(mode_value, plt.gca().get_ylim()[1] * 0.9, 'Moda', color='black', rotation=0)` `plt.axvline( x=quantile_25_value, color='yellow', linestyle='dashed', linewidth=2)plt.text(quantile_25_value, plt.gca().get_ylim()[1] * 0.3, 'Cuartil 1 (Q1)', color='yellow', rotation=0)` `plt.axvline( x=quantile_75_value, color='yellow', linestyle='dashed', linewidth=2)plt.text(quantile_75_value, plt.gca().get_ylim()[1] * 0.9, 'Cuartil 3 (Q3)', color='black', rotation=0)` `# Mostrar el gráficoplt.show()`
Hay distribuciones bimodales aún dentro del mismo pinguino. ![](https://static.platzi.com/media/user_upload/image-041debab-3478-4cde-a28d-1e4f305d498d.jpg)
```js sns.set_theme() fig3,ax3 = plt.subplots(1,len(numeric_columns)-1, figsize=(15,5)) for i in range(len(numeric_columns)-1): g=sns.violinplot( ax=ax3[i], data=pen_df, hue='species', legend= True if i == 3 else False, x=numeric_columns[i], palette = "inferno" ) sns.move_legend(g, 'lower center', bbox_to_anchor=(-1.3, 1.05), ncol=6, title='Especie') plt.show() ```Hay distribuciones bimodales aún entre el mismo tipo de pinguino. ![](https://static.platzi.com/media/user_upload/image-19505144-7ce7-47a9-bc69-6385c20c2463.jpg)
```js sns.set_theme() fig2,ax2 = plt.subplots(1,len(numeric_columns)-1, figsize=(15,5)) for i in range(len(numeric_columns)-1): g=sns.boxplot( ax=ax2[i], data=pen_df, hue='species', legend= True if i == 3 else False, x=numeric_columns[i], notch = True, palette = "inferno" ) sns.move_legend(g, 'lower center', bbox_to_anchor=(-1.3, 1.05), ncol=6, title='Especie') plt.plot() sns.reset_orig() ```Aquí muestro por una prueba no paramétrica que la diferencia entre cada especie en todos los datos numéricos es estadísticamente significativa. ![](https://static.platzi.com/media/user_upload/image-3759e8d1-d633-4cc9-b99f-1a37f2b5fbde.jpg)
Se están observando distribuciones con más de un punto crítico máximo gracias a la combinación de especies. ![](https://static.platzi.com/media/user_upload/image-48699b2f-4469-4758-ac4a-98756df922ea.jpg)
```python ```def freedman\_diaconis\_binwidth(x: pd.Series) -> float:    IQR = x.quantile(0.75) - x.quantile(0.25)    N = x.size    return 2 \* IQR / N\*\*(1/3) data = penguin\_dfbinwidth = freedman\_diaconis\_binwidth(data) bins = (penguin\_df.flipper\_length\_mm.max() - penguin\_df.flipper\_length\_mm.min())/binwidth\[2] sns.histplot(data = penguin\_df, x = 'flipper\_length\_mm',             bins = math.ceil(bins)) quantiles = penguin\_df.flipper\_length\_mm.quantile(\[0, 0.25, 0.5, 0.75, 1])desv = \[penguin\_df.flipper\_length\_mm.mean() + penguin\_df.flipper\_length\_mm.std(), penguin\_df.flipper\_length\_mm.mean() - penguin\_df.flipper\_length\_mm.std()]desv2 = \[penguin\_df.flipper\_length\_mm.mean() + penguin\_df.flipper\_length\_mm.std()\*2, penguin\_df.flipper\_length\_mm.mean() - penguin\_df.flipper\_length\_mm.std()\*2] plt.axvline(x = penguin\_df.flipper\_length\_mm.mean(),            color = 'red',            linewidth=2) for d in desv:    plt.axvline(x = d,                color = 'green',                linewidth = 2) for d2 in desv2:    plt.axvline(x = d2,                color = 'blue',                linewidth = 2) for q in quantiles:    plt.axvline(x=q,                 color='brown',                 linestyle='dashed') plt.show()
Aqui mi aportacion, creo que no es lo mejor para presentar los datos pero puse la media, los cuartiles 0.25 y 0.75 el valor maximo y minimo y la media mas/menos desviacion estandar y calculo el numero de bins. def freedman\_diaconis\_binwidth(x: pd.Series) -> float:    IQR = x.quantile(0.75) - x.quantile(0.25)    N = x.size    return 2 \* IQR / N\*\*(1/3) data = penguin\_dfbinwidth = freedman\_diaconis\_binwidth(data) bins = (penguin\_df.flipper\_length\_mm.max() - penguin\_df.flipper\_length\_mm.min())/binwidth\[2] sns.histplot(data = penguin\_df, x = 'flipper\_length\_mm',             bins = math.ceil(bins)) quantiles = penguin\_df.flipper\_length\_mm.quantile(\[0, 0.25, 0.5, 0.75, 1])desv = \[penguin\_df.flipper\_length\_mm.mean() + penguin\_df.flipper\_length\_mm.std(), penguin\_df.flipper\_length\_mm.mean() - penguin\_df.flipper\_length\_mm.std()]desv2 = \[penguin\_df.flipper\_length\_mm.mean() + penguin\_df.flipper\_length\_mm.std()\*2, penguin\_df.flipper\_length\_mm.mean() - penguin\_df.flipper\_length\_mm.std()\*2] plt.axvline(x = penguin\_df.flipper\_length\_mm.mean(),            color = 'red',            linewidth=2) for d in desv:    plt.axvline(x = d,                color = 'green',                linewidth = 2) for d2 in desv2:    plt.axvline(x = d2,                color = 'blue',                linewidth = 2) for q in quantiles:    plt.axvline(x=q,                 color='brown',                 linestyle='dashed') plt.show() ![](https://static.platzi.com/media/user_upload/fc0277f5-85b0-4f80-9cf4-6da704224832-b3c73fd9-9bd3-46e9-969f-12af0d301c77.jpg) ```python ```
La variable a la cual le saque los histogramas fue la de 'bill\_depth\_mm', en esta no se llega a ver una distribución binomial. ![](https://static.platzi.com/media/user_upload/Sin%20t%C3%ADtulo-744a01f7-1c61-4109-af9f-04befc60158c.jpg)
La diferencia en el histograma sucede por las diferencia entre especies, se pude ver en el siguiente histograma: ![](https://static.platzi.com/media/user_upload/Sin%20t%C3%ADtulo-2f676b14-32e5-405a-9bbd-2c8efd91bf0b.jpg)
mi hipótesis es que la longitud de las aletas de los pingüinos varían de acuerdo a la isla donde habitan ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA6AAAAMbCAYAAABTyPgHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABiEElEQVR4nO3deZxVdf0/8NedBRg2QUVRgUBNcgHBTNw1NRU3sjSt3Mq10lzya5hLaZZ+TbNEU9PU0m+5W5lkWm7f0qxc0tLcEENMRdn3We7vD37M1xEUGODcmeH5fDx84Dnnc85538985sx93bPcUrlcLgcAAABWsqpKFwAAAMCqQQAFAACgEAIoAAAAhRBAAQAAKIQACgAAQCEEUAAAAAohgAIAAFCImkoX0BY8+eSTKZfLqa2trXQpAAAA7U59fX1KpVKGDx/+ge2cAU1SLpdTLpeXeZ358+cv83p0PMYCCxkLvJvxwELGAgsZC7xbRxsPS5upnAFNms98DhkyZKnXmT17dp577rlsuOGG6dq168oqjXbAWGAhY4F3Mx5YyFhgIWOBd+to4+GZZ55ZqnbOgAIAAFAIARQAAIBCCKAAAAAUQgAFAACgEAIoAAAAhfAUXAAAYKk0Njamvr6+0mV0CPPmzWv+t6qqbZ8XrK2tTXV19QrZlgAKAAB8oHK5nDfeeCNTp06tdCkdRlNTU2pqavL666+3+QCaJL169Urfvn1TKpWWazsCKAAA8IEWhs+11lorXbt2Xe4QwoKzyfPmzUvnzp1X2NnFlaFcLmf27Nl56623kiTrrLPOcm1PAAUAAN5XY2Njc/hcY401Kl1Oh9HY2Jgk6dKlS5sOoElSV1eXJHnrrbey1lprLVe9bf9cLwAAUDEL7/ns2rVrhSuhkhb+/Jf3HmABFAAAWCKX3a7aVtTPXwAFAACgEAIoAAAAhRBAAQCADuGOO+7I4MGD89prry31OoMHD86YMWNWYlXvb++99843vvGNiuy7UgRQAAAACiGAAgAAHcKoUaPy9NNPZ7311qt0KbwP3wMKAAB0CNXV1W3+OzVXdc6AAgAAHcJ77wF95plncuSRR2bEiBEZOnRodtlll5x++ukfuI2JEyfmW9/6VvbYY48MHTo0I0aMyFe/+tVF7itduK/HH388559/frbeeusMGzYsX/nKVzJ58uQWbcvlcn70ox9lxx13zOabb55DDz00L7744op98e2EM6AAAECH88477+TII49M7969c8wxx6Rnz5557bXXct99933ges8880yefPLJ7L333unbt28mTpyYX/ziFznssMNy9913p66urkX78847Lz179szxxx+fiRMn5qc//WnOPffc/OAHP2hu88Mf/jBXXHFFdtppp+y000755z//maOPPjrz589fGS+9TRNAAQCADufJJ5/MtGnT8pOf/CRDhgxpnn/yySd/4Ho777xz9txzzxbzPv7xj+eggw7K7373u3zyk59ssaxXr1659tprUyqVkiRNTU254YYbMmPGjPTo0SOTJ0/ONddck5133jlXXnllc7uLL744P/7xj1fAK21fXIILAAB0OD169EiSPPjgg6mvr1/q9bp06dL8//X19ZkyZUoGDBiQnj175tlnn12k/Wc+85nmUJkkW265ZRobGzNx4sQkySOPPJL6+voccsghLdoddthhy/yaOgJnQAEAgA5nq622yh577JHLLrss119/fbbaaqvstttu2XfffdOpU6f3XW/u3Lm56qqrcscdd+TNN99MuVxuXjZjxoxF2q+77rotpnv27JkkmT59epLk9ddfT5IMHDiwRbvVV1+9ue2qRAAFAAA6nFKplEsvvTRPPfVUHnjggfzv//5vvvGNb+S6667LzTffnG7dui12vW9/+9u54447cvjhh2fYsGHp0aNHSqVSTj755BZhdKGqqsVfVLq4tgigAABABzZs2LAMGzYsJ598cu66666ceuqpGTt2bA488MDFtl94n+fo0aOb582bN2+xZz+XxsIzpOPHj0///v2b50+ePLn5LOmqxD2gAABAhzNt2rRFzkJuvPHGSfKBT59d3PeI3nDDDWlsbGxVHdtuu21qa2tz4403tqjnZz/7Wau21945AwoAAHQ4d955Z37xi19kt912y4ABAzJr1qzccsst6d69e3bcccf3XW/nnXfOr371q3Tv3j0bbrhhnnrqqTzyyCPp1atXq+pYffXV88UvfjFXXXVVjj322Oy000559tln8/DDD7d6m+2ZAAoAAHQ4W221VZ555pmMHTs2b7/9dnr06JGhQ4fmoosuanEp7HudccYZqaqqyl133ZV58+Zliy22yHXXXZejjjqq1bWcdNJJ6dSpU2666aY89thjGTp0aK6++uocd9xxrd5me1Uquzs2zzzzTJK0+H6gJZk9e3aee+65bLzxxunatevKKo12wFhgIWOBdzMeWMhYYKH2Ohbmzp2bV155JYMGDWrxFSUsn8bGxsydOzddunRZ7GW/bc2SxsHSZir3gAIAAFAIARQAAIBCCKAAAAAUQgAFAACgEAIowApSKpVSV1eXUqlU6VIAANokX8MCsByayk2pKi34LK+uri6bbLJJhStqH97dbwDAqkMABVgOVaWq3PfqfZkyd0oaGhoyZcqU9O7dOzU1Dq/vp3eX3vnEhz5R6TIAgArwDglgOU2ZOyVvz3k79fX1mTR9Uho6N6S2trbSZQEAtDmufwIAAKAQAigAAACFcAkuAADQ4Q0ePHiJbc4///x86lOfKqCaVZcACgAAtEpTuZyqCn392LLu++abb24xfdBBB+XQQw/NPvvs0zxvwIABK6w+Fk8ABQAAWqWqVMpvn/lPJs+aX+h+V+/WKSOHrLNM6wwbNmyReeuss85i5y+LuXPnpkuXLsu1jbawj6K4BxQAAGi1ybPm560Z8wr9b2UE3qampvzoRz/KLrvsks022yx77rlnbrrpphZtxowZk+HDh+fpp5/OQQcdlCFDhuR//ud/kiR/+9vf8slPfjJDhgzJvvvumz/96U8ZNWpURo8e3WIbTz75ZA477LB89KMfzY477pj/+q//yjvvvNO8/LXXXsvgwYNzxx135Mwzz8yIESNy4IEHJkkef/zxfP7zn89HP/rRDB8+PPvuu2/uvPPOFtt/8MEHc+CBB2bo0KHZeuut881vfjOzZ89uXv7YY49l8ODB+dOf/pSvfe1rGT58eD7+8Y/n6quvXqH9+X6cAQUAAFZ5F154YX72s5/lS1/6UoYPH54HH3ww3/zmN9PQ0JBDDjmkuV19fX2+9rWv5YgjjsjJJ5+cXr165a233srRRx+dTTbZJD/4wQ8yY8aMfOtb38qMGTOy8cYbN6/75JNP5tBDD81OO+2Uiy++ONOmTcsVV1yRL3/5y4tcIvz973+/uV1TU1NmzpyZY489Nh/96Efz/e9/P506dcpLL72U6dOnN69zzz335OSTT86nPvWpnHDCCZk0aVIuvvjiTJ8+PZdcckmL7X/zm9/MqFGjcvnll+f3v/99LrroogwePDg77rjjSurhBQRQAABglTZ58uTceOONOfLII3PCCSckSbbffvtMmTIll19+eT772c+muro6yYIAevLJJ2evvfZqXv/CCy9MdXV1rrrqqnTv3j1J0q9fv3z+859vsZ+LL744m222WS677LI0NTVl7ty52XTTTTNq1Kg89NBD2WmnnZrbfuQjH8l3vvOd5ulnnnkmM2bMyCmnnNL8QKVtttmmeXm5XM6FF16Yvfbaq8V6ffr0yTHHHJMvf/nL+fCHP9w8f/fdd29+rdtss00efPDB/O53v1vpAdQluAAAwCrt6aefTn19ffbcc88W80eOHJnJkydn/PjxLea/OygmC8LhiBEjmsNnkmy55Zbp1atX8/ScOXPyxBNPZM8990xjY2MaGhrS0NCQgQMHZp111skzzzzTYps777xzi+kBAwake/fu+da3vpWxY8dm8uTJLZa/8sormThxYkaOHNm87YaGhmy11VapqqrKP/7xjxbtt99+++b/L5VK2WCDDfLGG298YD+tCM6AAgAAq7Rp06YlSdZcc80W8xdOT506tXleXV1dunXr1qLdpEmTMnDgwEW2u/rqqzf///Tp09PY2Jjzzz8/559//iJt//Of/7SYXmONNVpMr7baarnuuuty6aWX5rTTTktjY2O23HLLnHnmmRk8eHCmTJmSJPnKV76y2Nf43u336NGjxXRtbW1mzJix2HVXJAEUAABYpS08U/nOO+9k7bXXbp7/9ttvt1ieLDhb+F59+vRZ5IxkkhbzevTokVKplGOPPTa77bZbmpqaMn/+/HTq1ClVVVXp3bt3i3UXt5+hQ4fmmmuuydy5c/PYY4/lv//7v/OVr3wlv//975trPPvsszN06NBF1l1rrbXevwMKJIACAACrtCFDhqS2tjb33HNPNtlkk+b5v/3tb7PGGmss9uzme9e/+eabM3PmzObLcP/2t7+1OHPatWvXDBs2LOPGjcuQIUPS2NjY/PUqC+8vXVpdunTJTjvtlH//+9/5zne+k3nz5mX99ddP3759M2HChEXuPW1LBFAAAGCVtvrqq+eQQw7JT37yk3Tq1CnDhg3LQw89lN/85jc566yzlhgQjzjiiPziF7/IsccemyOPPDLTp0/P5Zdfnt69e7c4k3naaafl8MMPz0knnZSRI0emS5cumTx5cv785z/nU5/6VEaMGPG++3jwwQdz2223Zbfddsu6666bt99+OzfeeGO22GKLdO7cOUkyevTonHrqqZk9e3Z23nnn1NXV5fXXX89DDz2Uk08+OYMGDVoxHbYcBFAAAKDVVu/WqUPs87TTTkuPHj1y22235corr8x6662Xc845JwcffPAS111rrbVy9dVX57zzzstXv/rVDBgwIGeccUbOPffcFvdabrHFFvn5z3+eMWPG5Iwzzkh9fX3WXnvtbLPNNvnQhz70gfsYMGBAqqqq8oMf/CDvvPNOevXqle233z6nnHJKc5uRI0emZ8+eufLKK3PXXXclSdZbb73ssMMOi9zfWimlcrlcrnQRlbbwiVNDhgxZ6nVmz56d5557LhtvvHG6du26skqjHTAWuOX5W/L2nLdTX1+fSZMmpU+fPqmtra10WW3WmnVr5jODP1PpMlY6xwYWMhZYqL2Ohblz5+aVV17JoEGD0qVLlxbLmsrlVC3mXsUiVHLfS2P8+PEZOXJkvvvd72b//fdfZPnyXIJbCR80DpKlz1TOgAIAAK1SyQDY1sLnxRdfnMGDB2ettdbKhAkTctVVV6VPnz7ZfffdK11amyKAAgAALKf6+vpcdNFFefvtt9OlS5dstdVWOe200xb5ypZVnQAKAACwnEaPHp3Ro0dXuow2r6rSBQAAALBqEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAFYJY8aMyeDBg5v/GzJkSEaOHJmrr746TU1NSZLXXnstgwcPzj333FPhajummkoXAAAAtFPlpqRUoXNardx3ly5d8tOf/jRJMnfu3Dz22GO5+OKLUy6Xc8wxx2SttdbKzTffnIEDB67ggkkEUAAAoLVKVcmzv05mvV3sfrutmWyyX6tWraqqyrBhw5qnt95667zwwgu59957c8wxx6RTp04tlrNiCaAAAEDrzXo7mflmpatYLt26dUtDQ0OSBZfg7rrrrvnhD3+YPffcM0nyhz/8IZdffnleeeWVVFdXZ8CAATnxxBOz0047NW/jl7/8Za6//vq8/PLL6dq1a4YOHZpvfetbWW+99ZIkzz//fC688MI8/vjjqa6uzrbbbpsTTzwxgwYNat5GuVzOtddem1tuuSUTJ07M2muvnUMPPTRHHHFEcZ2xkgmgAADAKmVh2Fx4Ce69996bY489drFt//3vf+fEE0/M3nvvna997WtpamrKv/71r0ybNq25zTXXXJPvfe97OeCAA3LyySenvr4+f/7znzN58uSst956+c9//pNDDjkk/fv3z/e+973Mmzcvl1xySY4++uj86le/Ss+ePZMk3/nOd3LrrbfmuOOOy+abb54nnngiF110UTp37pzPfvazK79jCiCAAgAAq4zZs2dn0003bTFvr732yjHHHLPY9s8++2zq6+tz1llnpXv37kmSHXbYoXn5jBkzctlll+Wggw7Kueee2zx/t912a/7/66+/Pg0NDbn22mvTq1evJMngwYOz77775s4778zhhx+ef//737nxxhtzzjnn5KCDDkqSbLvttpk7d24uv/zyHHTQQamqav/PkG3/rwAAAGApdenSJbfddltuu+22/PznP88ZZ5yR//3f/82ZZ5652PaDBw9OdXV1Tj311Nx///2ZMWNGi+VPPvlk5syZkwMOOOB99/m3v/0tI0aMaA6fSbL++utno402yhNPPJEkeeSRR5Iku+++exoaGpr/23bbbTNp0qT85z//Wc5X3jY4AwoAAKwyqqqqMmTIkObpj370o2lsbMwFF1yQL3zhC+natWuL9oMGDcqVV16Zq666Kscff3yqqqqy/fbb5+yzz866666bqVOnJknWWmut993n9OnTs/HGGy8yf/XVV2++lHfKlCkpl8vZeuutF7uN//znP833k7ZnAigAALBKW3/99ZMkL730UoYOHbrI8h133DE77rhjZs6cmYcffjjnn39+Tj/99Pz0pz9tPqv51ltvpW/fvovd/mqrrZZ33nlnkfmTJ09ufgjRaqutllKplJ///Oepra1dpO27H1bUngmgAADAKu3FF19MkvTu3fsD23Xv3j177bVXnn766fzmN79JkgwfPjx1dXW5/fbbFxtekwVnWW+55ZZMmzYtq622WpLklVdeyYsvvphPf/rTSZJtttkmSTJ16tTssssuK+R1tUUCKAAA0Hrd1mxX+2xqaspTTz2VJKmvr88///nPXHHFFdlwww2z5ZZb5s03W36lzE033ZSnnnoqO+ywQ/r06ZPXXnstv/71r7PddtslSXr06JGvfOUrueiii1Iul7Prrrumqakpjz32WPbee+8MGTIkRxxxRO6444588YtfzJe+9KXmp+D27ds3+++/f5IFZzg///nP57TTTsuRRx6ZzTffPPX19Rk/fnwee+yx/OhHP2r1a25LBFAAAKB1yk3JJvtVbt+lZX+m6ty5c5ufMltTU5O+fftmv/32y/HHH7/YS18HDx6cBx54IOeff36mTp2aPn36ZO+9986JJ57Y3Oboo4/O6quvnuuvvz533HFHunXrluHDh2eNNdZIkqyzzjq54YYbcuGFF+bUU09NVVVV8/eAduvWrXk7Z555ZgYNGpSbb745l19+ebp165ZBgwY1fx9pRyCAAgAArdOKAFjJfZ9wwgk54YQTPrBNv3798vzzzzdPDx8+PFddddUSt/3pT3+6+XLaxfnIRz6Sa6+9tnm6sbExc+fObdGmVCrlkEMOySGHHLLE/bVXvoYFAACAQgigAAAAFKLNBtBZs2Zlxx13zODBg/PMM8+0WHbrrbdmjz32yJAhQ7LffvvlgQceqFCVAAAALK02G0B/9KMfpbGxcZH5d999d84666yMHDkyV199dYYNG5bjjz+++UlWAAAAtE1tMoC+/PLL+fnPf77YG4QvvfTS7L333jnppJOy9dZb59xzz82QIUNy+eWXV6BSAAAAllabDKDnnXdeDj744AwaNKjF/AkTJmT8+PEZOXJki/l77bVXHn300cyfP7/IMgEAAFgGbe5rWO6555688MILGTNmTP75z3+2WDZu3LgkWSSYbrDBBqmvr8+ECROywQYbtGq/5XI5s2fPXur2c+bMafEvqy5jYdVVKpVSV1eXhoaG1NfXp76+Pkma/2XxGmobkiz4nSmXyxWuZuVxbGAhY4GF2utYmDdvXpqamtLY2LjYW+RonYV/A8vlcrvo18bGxjQ1NWXOnDlpampaZHm5XE6pVFridtpUAJ0zZ04uuOCCnHzyyenevfsiy6dNm5Yk6dmzZ4v5C6cXLm+N+vr6PPfcc8u83vjx41u9TzoWY2HVU1dXl0022SRTpkzJpOmTmudPnTq1ckW1AzU9F/zpeeWVV9rdm7DWcGxgIWOBhdrjWKipqcm8efMqXUaH1F76dd68eWloaGg+Kbg4nTp1WuJ22lQAveKKK7LGGmt84Be4riy1tbXZcMMNl7r9nDlzMn78+AwcODB1dXUrsTLaOmNh1bXwU77evXunofOCs6BTp05Nr169UltbW+Hq2q7eXXsnWXA1S0c/A+rYQGIs8H/a61iYN29eXn/99XTu3DldunSpdDkdRrlczrx589K5c+elOnPYFtTU1GTAgAHp3LnzIsteeumlpdvGii6qtSZOnJhrr702l19+eWbMmJEkzZfEzp49O7Nmzcpqq62WJJkxY0b69OnTvO706dOTpHl5a5RKpXTt2nWZ16urq2vVenQ8xsKqq6ampkXgrK2tFUA/QE3Ngj897enN1/JwbGAhY4GF2ttYqKqqSlVVVaqrq1NdXV3pcjqMhZfdlkqldtGv1dXVqaqqSl1d3WI/iFjaEN1mAuhrr72W+vr6HHPMMYssO+yww7L55pvn4osvTrLgXtD111+/efm4ceNSW1ub/v37F1YvAACs6prKTakqVea5pq3Z95gxY3LZZZclWRCYunXrlnXXXTcf+9jH8vnPf77Vz5Nh6bWZALrxxhvnZz/7WYt5zz33XM4///ycc845GTJkSPr375+BAwfmnnvuyW677dbcbuzYsdlmm22W6ppjAABgxagqVeW+V+/LlLlTCt1v7y6984kPfaJV63bp0iU//elPkySzZs3KCy+8kJtvvjm33HJLvvOd72TUqFErslTeo80E0J49e2bEiBGLXbbppptm0003TZKccMIJOfXUUzNgwICMGDEiY8eOzdNPP50bb7yxyHIBAIAkU+ZOydtz3q50GUutqqoqw4YNa57ebrvt8rnPfS7HHHNMzjjjjGyxxRaLvbJy/vz5qampSVVVm/wmy3aj3fXePvvsk29/+9v5zW9+kyOPPDJPPPFELrvssgwfPrzSpQEAAO1Q586dc9ZZZ6W+vj633nprkmSXXXbJueeem6uvvjof//jHM3To0OYn3d9xxx3Zd999M2TIkOywww655JJLWnyVyltvvZXTTz89u+66a4YOHZrdd9893//+9zN//vwW+91iiy1yzTXX5JJLLsk222yTLbfcMhdeeGHK5XIeffTRjBo1KsOHD8/hhx+e//znP4X1x8rUZs6ALs6IESPy/PPPLzL/wAMPzIEHHliBigAAgI5oww03zNprr50nn3yyed69996bD33oQznjjDNSVVWVrl275rrrrsv3vve9HH744Rk9enRefvnl5gB66qmnJkmmTJmSXr165fTTT0/Pnj0zfvz4jBkzJpMmTcr555/fYr8///nPs9VWW+XCCy/M3//+94wZMyZNTU3505/+lC996Uupra3NeeedlzPOOCPXXnttoX2yMrTpAAoAAFCUddZZJ2+//X+XE9fX1+fqq69ufmrxzJkzc+mll+aoo47KKaeckmTBJby1tbW54IILcuSRR6Z3794ZPHhwvv71rzdvZ4sttkhdXV1Gjx6ds88+u8WT4Pv06ZPvfe97SZIddtgh999/f66//vrcfffdzQ9FevPNN/Ptb38706dPT8+ePVd6P6xMAigAAEAWfDfnu79OZMSIES2+MufJJ5/M7Nmzs+eee6ahoaF5/rbbbpu5c+fmxRdfzFZbbZVyuZyf/vSnueWWW/Laa69l3rx5zW0nTJiQjTbaqMW67zZo0KC8/fbbLZ7IO3DgwCTJG2+8IYACAAB0BG+88UZz2EuSNdZYo8XyKVMWPO13//33X+z6C+/T/OlPf5r//u//zlFHHZURI0akZ8+eeeaZZ3Luuee2CKNJ0qNHjxbTtbW1i4TMhd8v/t512yMBFAAAWOW9+OKLefPNN1uEy3efDU2S1VZbLUly2WWXpW/fvotso1+/fkmSe+65J7vssku+9rWvNS97+eWXV0bZ7Y4ACgAArNLmzZuXb3/72+nUqdMHPux0+PDhqauryxtvvJFPfOL9v4d07ty5zWctF7rrrrtWWL3tmQAKAAC0Wu8uvdvVPpuamvLUU08lSWbPnp0XXnghN998cyZMmJALLrig+Szm4vTs2TNf/epX873vfS9vvPFGttpqq1RXV2fChAn5wx/+kDFjxqSuri7bbrttfvazn+XGG2/MwIED8+tf/zqvvvpqq2vuSARQAACgVZrKTfnEh97/TODK3ndVqWqZ15s7d24OOuigJEnXrl3Tr1+/bLPNNrnssstaPPjn/Xzxi1/M2muvneuuuy433nhjampqMmDAgOy8887NZz2/8pWvZMqUKbn00kuTJHvssUfOPPPMHHfccctcb0cjgAIAAK3SmgBYyX2fcMIJOeGEE5aq7f333/++y/bee+/svffe77u8W7dui3zfZ5I8//zzLaafeOKJdOnSpcW8Cy64YJH1RowYsci67VXlRgwAAACrFAEUAACAQgigAAAAFEIABQAAoBACKAAAsETlcrnSJVBBK+rnL4ACAADva+FXi8yePbvClVBJC3/+C8dDa/kaFgAA4H1VV1enV69eeeutt5Is+O7MUqlU4arav8bGxsybNy/Jgj5uq8rlcmbPnp233norvXr1Wu5aBVAAAOAD9e3bN0maQyjLr6mpKQ0NDampqUlVVdu/MLVXr17N42B5CKAAAMAHKpVKWWeddbLWWmulvr6+0uV0CHPmzMm4ceMyYMCA1NXVVbqcD1RbW7vCztIKoAAAwFKprq5u05eLtidNTU1Jks6dO6dLly4VrqY4bf9cLwAAAB2CAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQDg/5SbKl1B+6TfYKn4HlAAAP5PqSp59tfJrLcrXUn70W3NZJP9Kl0FtAsCKAAALc16O5n5ZqWrADogl+ACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKADASlQqlVJXV5dSqVTpUgAqrqbSBQAArDTlpqRU2c/b6+rqsskmm1S0BoC2QgAFADquUlXy7K+TWW9XrIT6hoZMnTolvXr1Tm1NG3/rtcYGyfo7VboKoANr40dBAIDlNOvtZOabldt/fX3qp0xKqucltbWVq2NpdF2j0hUAHZx7QAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIVoUwH0oYceyiGHHJKtt946m222WXbdddecf/75mTFjRot2999/f/bbb78MGTIke+yxR26//fYKVQwAAMDSqql0Ae82derUDB06NIceemh69eqVF198MWPGjMmLL76Ya6+9Nknyt7/9Lccff3wOOOCAfOMb38if//znnHHGGenWrVv23HPPCr8CAAAA3k+bCqCjRo1qMT1ixIh06tQpZ511Vt58882svfbaueKKKzJ06NCce+65SZKtt946EyZMyKWXXiqAAgAAtGFt6hLcxenVq1eSpL6+PvPnz89jjz22SNDca6+98vLLL+e1116rQIUAAAAsjTZ1BnShxsbGNDQ05KWXXsrll1+eXXbZJf369ctLL72U+vr6rL/++i3ab7DBBkmScePGpV+/fq3aZ7lczuzZs5e6/Zw5c1r8y6rLWFh1lUql1NXVpaGhIfX19amvr0+S5n9ZvIbahiQLfmfK5XKFq1l5HBsqb+HvaH1DQ1LB38v6hvoW/7ZpjQ2pTVLfWNk+a3caFvTbko5rjgu8W0cbD+VyOaVSaYnt2mQA/fjHP54333wzSbLDDjvk4osvTpJMmzYtSdKzZ88W7RdOL1zeGvX19XnuueeWeb3x48e3ep90LMbCqqeuri6bbLJJpkyZkknTJzXPnzp1auWKagdqei740/PKK690mD+6H8SxoXIW/o5OnTol9VMmLXmFlaw9HBvqus1I7yQzp8/InLcr32ftRW1j5/TJ0h/XHBd4t440Hjp16rTENm0ygP74xz/OnDlz8tJLL+WKK67Icccdl+uuu26l7rO2tjYbbrjhUrefM2dOxo8fn4EDB6aurm4lVkZbZyysuhZ+yte7d+80dF5wFnTq1Knp1atXamtrK1xd29W7a+8kyaBBgzr8GVDHhspa+Dvaq1fvpHpexeqob3jXsaGmjR8bevRIknTv2SPd06fCxbQjPZbuuOa4wLt1tPHw0ksvLVW7NhlAP/KRjyRJhg8fniFDhmTUqFG57777mgPie7+WZfr06UmS1VZbrdX7LJVK6dq16zKvV1dX16r16HiMhVVXTU1Ni8BZW1srgH6AmpoFf3o6wh/bpeHYUHm1NTVJG/idrK1pB8eG6gW/n7XVbaPP2o1lPK45LvBuHWU8LM3lt0k7eAjR4MGDU1tbm3//+98ZMGBAamtrM27cuBZtFk6/995QAAAA2o42H0D//ve/p76+Pv369UunTp0yYsSI/O53v2vRZuzYsdlggw1a/QAiAAAAVr42dQnu8ccfn8022yyDBw9Oly5d8q9//Ss/+clPMnjw4Oy2225Jki996Us57LDD8q1vfSsjR47MY489lt/85je55JJLKlw9AAAAH6RNBdChQ4dm7Nix+fGPf5xyuZz11lsvBx54YI488sjmJyptueWWGTNmTH7wgx/ktttuy7rrrpvzzjsvI0eOrHD1AAAAfJA2FUCPOeaYHHPMMUtst+uuu2bXXXctoCIAAABWlDZ/DygAAAAdgwAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigArASlUil1dXUplUqVLgVoIxwXIKmpdAEArFq61nRNU7kpVaWO/RloXV1dNtlkkxW2vVWhz6Dd6tQtKTclS/gdXdHHhXZvKfqMjkcABaBQnao7papUlftevS9T5k6pdDkrTUNDQ6ZMmZLevXunpmb5/tz27tI7n/jQJ1ZQZcAKV9NlQZB69tfJrLfft1l9Q0OmTp2SXr16p3Y5jwvtXrc1k032q3QVVMAqPvIBqJQpc6fk7Tnv/0atvauvr8+k6ZPS0LkhtbW1lS4HKMKst5OZb77/8vr61E+ZlFTPSxwXWEU55w0AAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABZo1lZsqXQIAAB1YTaULANqOqlJV7nv1vkyZO6XSpbQLA3oOyNbrbF3pMgAA2g0BFGhhytwpeXvO25Uuo13o1blXpUsAAGhXXIILAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQrQ6ghx12WB599NH3Xf7nP/85hx12WGs3DwAAQAfT6gD6l7/8JW+//fb7Lp88eXL++te/tnbzAAAAdDDLdQluqVR632WvvvpqunXrtjybBwAAoAOpWZbGd955Z+68887m6SuuuCK33HLLIu1mzJiR559/PjvuuOPyVwgAAECHsEwBdM6cOZkyZUrz9KxZs1JVtehJ1K5du+bggw/OV77yleWvEAAAgA5hmQLo5z73uXzuc59Lkuyyyy4544wzsuuuu66UwgAAAOhYlimAvtv999+/IusAAACgg2t1AF1o5syZef311zN9+vSUy+VFln/sYx9b3l0AAADQAbQ6gE6ePDnnnXde7r333jQ2Ni6yvFwup1Qq5bnnnluuAgEAAOgYWh1Azz777DzwwAM59NBDs+WWW6Znz54rsi4AAAA6mFYH0D/96U85/PDDc9ppp63IegAAAOigFv0OlaXUpUuXrLfeeiuyFgAAADqwVgfQ/fbbL7///e9XZC0AAAB0YK2+BHePPfbIX//61xx55JE56KCD0rdv31RXVy/SbtNNN12uAgEAAOgYWh1AP/e5zzX//yOPPLLIck/BBQAA4N1aHUDPP//8FVkHAAAAHVyrA+j++++/IusAAACgg2v1Q4gAAABgWbT6DOjpp5++xDalUinf/e53W7sLAAAAOpBWB9DHHntskXlNTU2ZNGlSGhsbs/rqq6eurm65igMAAKDjaHUAvf/++xc7v76+PjfffHN++tOf5tprr211YQAAAHQsK/we0Nra2hxyyCHZbrvt8u1vf3tFbx4AAIB2aqU9hOgjH/lI/vrXv66szQMAANDOrLQA+sgjj7gHFAAAgGatvgf0sssuW+z8GTNm5K9//WueffbZHHPMMa0uDAAAgI5lhQfQ1VZbLf37988555yTz3zmM60uDAAAgI6l1QH0X//614qsAwAAgA5upd0DCgAAAO/W6jOgC/3lL3/Jgw8+mNdffz1Jsu6662bnnXfOVltttdzFAQAA0HG0OoDOnz8/X/va1/L73/8+5XI5PXv2TJJMnz491113XT7xiU/k4osvTm1t7QorFgAAgPar1ZfgXn755bnvvvvyhS98IX/84x/zl7/8JX/5y1/ypz/9KV/84hdz77335vLLL1+RtQIAANCOtTqA3nXXXdl///1z2mmnZc0112yev8Yaa+S//uu/8slPfjK//vWvV0iRAAAAtH+tDqCTJk3K0KFD33f50KFDM2nSpNZuHgAAgA6m1QG0b9+++ctf/vK+y//617+mb9++rd08AAAAHUyrA+gnP/nJ/Pa3v83ZZ5+dcePGpbGxMU1NTRk3bly++c1v5p577sn++++/ImsFAACgHWv1U3CPO+64TJgwIbfccktuvfXWVFUtyLJNTU0pl8vZf//9c9xxx62wQgEAAGjfWh1Aq6urc8EFF+SII47Iww8/nIkTJyZJ1ltvvey44475yEc+ssKKBAAAoP1bpgA6b968fOc738mHP/zhHHrooUmSj3zkI4uEzZ/97Ge56aabcsYZZ/geUAAAAJIs4z2gN998c+68887svPPOH9hu5513zu23355bb711eWoDAACgA1mmAPrb3/42u+++e/r37/+B7QYMGJA999wzd99993IVBwAAQMexTAH0hRdeyEc/+tGlajt8+PA8//zzrSoKAACAjmeZAmh9ff1S39NZW1ub+fPnt6ooAAAAOp5lCqBrrbVWXnzxxaVq++KLL2attdZqVVEAAAB0PMsUQLfddtv86le/yjvvvPOB7d5555386le/yrbbbrtcxQEAANBxLFMAPfroozNv3rwcfvjh+fvf/77YNn//+99zxBFHZN68eTnqqKNWSJEAAAC0f8v0PaD9+/fPD37wg5xyyik5+OCD079//2y00Ubp1q1bZs2alRdffDH//ve/06VLl3z/+9/PgAEDVlbdAAAAtDPLFECTBd/x+etf/zpXX311Hnzwwfz+979vXrbWWmvlwAMPzNFHH73Er2oBAABg1bLMATRJ+vXrl3POOSdJMnPmzMyaNSvdunVL9+7dV2hxAAAAdBytCqDv1r17d8ETAACAJVqmhxABAABAawmgAAAAFEIABQAAoBACKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQrSpAPrb3/42X/rSl7Ljjjtm2LBhGTVqVG677baUy+UW7W699dbsscceGTJkSPbbb7888MADFaoYAACApdWmAuj111+furq6jB49OldccUV23HHHnHXWWbn88sub29x9990566yzMnLkyFx99dUZNmxYjj/++Dz11FOVKxwAAIAlqql0Ae92xRVXZPXVV2+e3mabbTJ16tRcd911+fKXv5yqqqpceuml2XvvvXPSSSclSbbeeuu88MILufzyy3P11VdXqHIAAACWpE2dAX13+Fxo4403zsyZMzN79uxMmDAh48ePz8iRI1u02WuvvfLoo49m/vz5RZUKAADAMmpTZ0AX5/HHH8/aa6+d7t275/HHH0+SDBo0qEWbDTbYIPX19ZkwYUI22GCDVu2nXC5n9uzZS91+zpw5Lf5l1dVRxkKpVEpdXV0aGhpSX19f6XLahcbGxiRp7rOF/ab/Pth7+62jWpHjoaG2IcmC48x7n4vA+1t4XKtvaEgqONbqG+pb/NumNTakNkl9Y2X7rN1Zyn5rV2NhZWtY0Ger8nGto7yHXKhcLqdUKi2xXZsOoH/7298yduzYfP3rX0+STJs2LUnSs2fPFu0WTi9c3hr19fV57rnnlnm98ePHt3qfdCztfSzU1dVlk002yZQpUzJp+qRKl9Mu9K3pmySZMWNGJk3+vz6bOnVqhSpqH96v3zqqFTEeanou+HP9yiuvdJg3KkVYeFybOnVK6qdUfqy1h2NDXbcZ6Z1k5vQZmfN25fusvVjWfmsPY2Flq23snD5xXEva/3vId+vUqdMS27TZAPrGG2/k5JNPzogRI3LYYYet9P3V1tZmww03XOr2c+bMyfjx4zNw4MDU1dWtxMpo6zrKWFj4iVXv3r3T0LmhwtW0Dws//OrRo0f6VPdJfX19pk6dml69eqW2trbC1bVd7+23jmpFjofeXXsnWXAF0Kp6pqA1Fh7XevXqnVTPq1gd9Q3vGgs1bfzY0KNHkqR7zx7pno77+7nCLWW/tauxsLL1cFzrKO8hF3rppZeWql2bDKDTp0/P0UcfnV69emXMmDGpqlpwq+pqq62WZMGn5n369GnR/t3LW6NUKqVr167LvF5dXV2r1qPj6ShjoaamRnhaStXV1UkW7bPa2lp9+AHer986qhUxHmpqFvy57ghvUCqhtqYmaQNjrbamHRwbqheMtdrqttFn7cYy9lu7GAsrm+Nas47yHnJpLr9N2thDiJJk7ty5OfbYYzNjxoxcc8016fH/P1FKkvXXXz9JMm7cuBbrjBs3LrW1tenfv3+htQIAALD02lQAbWhoyEknnZRx48blmmuuydprr91ief/+/TNw4MDcc889LeaPHTs222yzzVJdcwwAAEBltKlLcM8555w88MADGT16dGbOnJmnnnqqedkmm2ySTp065YQTTsipp56aAQMGZMSIERk7dmyefvrp3HjjjZUrHAAAgCVqUwH0T3/6U5LkggsuWGTZH/7wh/Tr1y/77LNP5syZk6uvvjo//vGPM2jQoFx22WUZPnx40eUCAACwDNpUAL3//vuXqt2BBx6YAw88cCVXAwAAwIrUpu4BBQAAoOMSQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFKJNfQ8oQHvUq3OvJElDbUNqetakd9feqalxeH0/PTr1qHQJAECFeIcE0EpdqrukqVzO7gN3r3Qp7U5TuZyuNV0rXQYAUDABFKCVaqtrU1Uq5epH/5pXJk9KU1M5c+fMSZe6ulRVlSpdXpu10Zrr5YgRm6dTdadKlwIAFEwABVhO/5k+I+MnT0lTU1NmzZqVbt26parKLfbvp2en1SpdAgBQId4hAQAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEIIoAAAABRCAAUAAKAQAigAAACFEEABAAAohAAKAABAIQRQAAAACiGAAgAAUAgBFAAAgEII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pLN+W1b6bdnps9bRb8tOn7WOfmuFms5JOle6ivantssHLi79//94lyX0WUe2PONhZZ8Aa41SqbRUdbW7ALoyDB8+vNIlAAAAdHjt7h7Qnj17ZsaMGYvMnzZtWlZbbbUKVAQAAMDSaHcBdP3118+4ceNazJsxY0YmTZqU9ddfv0JVAQAAsCTtLoDuuOOOeeSRRzJ9+vTmeffcc0+qqqqy3XbbVbAyAAAAPki7ewrutGnTsvfee2fQoEE59thj8+abb+aCCy7Ivvvum7PPPrvS5QEAAPA+2l0ATZKXX3453/72t/Pkk0+mW7duGTVqVE4++eRCn0oLAADAsmmXARQAAID2p93dAwoAAED7JIACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAAAIUQQP+/V199NWeffXZGjRqVTTbZJPvss0+L5a+99loGDx682P+GDBnSou2MGTPyjW98I1tttVWGDx+er371q3nrrbeKfDkshyWNhSSZM2dOLr744uy6667ZfPPNs8cee+TKK69MQ0NDi3bGQvu3NONh/vz5+d73vpftt98+Q4cOzQEHHJBHH310se3++7//O9ttt12GDRuWL3zhCxk3blwRL4Pl9Nvf/jZf+tKXsuOOO2bYsGEZNWpUbrvttrz3m8xuvfXW7LHHHhkyZEj222+/PPDAA4tsy3Gh/Vua8TB27NiccMIJ2XHHHTN48OD85Cc/Wey2jIf2bUljYebMmRkzZkwOOOCAbLnlltl2221z3HHH5fnnn19kW8ZC+7Y0x4X//u//zt57753hw4dniy22yKc//encfffdi2yro79fqKl0AW3Fiy++mIceeiibb755mpqaFnlTsdZaa+Xmm29uMa9cLueoo47K1ltv3WL+SSedlJdeeinf+ta30rlz5/zgBz/I0Ucfndtvvz01Nbq8rVvSWEiSc889N/fee29OOeWUbLDBBnnqqady6aWXZs6cOTn55JOb2xkL7d/SjIfvfve7+dWvfpWTTjopgwYNyh133JGjjz46N998czbddNPmduedd17Gjh2b0aNHZ+21186VV16ZI444InfffXd69OhR5MtiGV1//fVZb731Mnr06PTu3TuPPPJIzjrrrLzxxhs5/vjjkyR33313zjrrrBx33HHZeuutM3bs2Bx//PH5n//5nwwbNqx5W44L7d/SjId77rknEyZMyM4777zI+4d3Mx7atyWNhddffz0333xzPv3pT+ekk07KvHnzcu211+aggw7K7bffng022KB5W8ZC+7Y0x4VZs2blwAMPzPrrr59SqZTf/e53OeWUU9LU1JR99923eVsd/v1CmXK5XC43NjY2///Xv/718t57773Edf785z+XN9poo/LYsWOb5z3xxBPljTbaqPy///u/zfNefvnl8uDBg8t33333ii2alWJJY6GxsbG8+eably+99NIW80877bTyrrvu2jxtLHQMSxoPb7zxRnnjjTcu/+xnP2ue19TUVN5nn33Kxx13XPO8//znP+WNN964fNNNNzXPmzJlSnnYsGHlH//4xyvxFbAivPPOO4vMO/PMM8tbbLFF8xjZfffdy6ecckqLNgcddFD5qKOOap52XOgYlmY8vPvYsdFGG5WvueaaRdYxHtq/JY2FWbNmlWfPnt1i+cyZM8tbbbVV+dxzz22eZyy0f0tzXFicgw46qPyFL3yheXpVeL/gEtz/r6pq2bviN7/5Tbp3755ddtmled7DDz+cnj17Zrvttmuet/7662fjjTfOww8/vEJqZeVa0lgol8tpaGhY5BOoHj16tDg7Zix0DEsaD//617/S2NjY4udcKpWy/fbb549//GPmz5+fJPnjH/+Ypqam7Lnnns3tevXqle222854aAdWX331ReZtvPHGmTlzZmbPnp0JEyZk/PjxGTlyZIs2e+21Vx599NHmceC40DEsaTwkS/e+wnho/5Y0Frp27Zq6uroWy7t165YBAwa0uLzWWGj/lua4sDi9evVKfX198/Sq8H5BAG2l+vr63HvvvfnEJz6Rzp07N88fN25cBg0alFKp1KL9+uuv36Gu3V6VVVdX51Of+lRuvPHGPP3005k1a1YeeeSR/OpXv8ohhxzS3M5YWDUsDBadOnVqMb9Tp06ZP39+XnvttSQLxsMaa6yR1VZbrUW7DTbYwHhopx5//PGsvfba6d69e/PPcNCgQS3abLDBBqmvr8+ECROSOC50ZO8eD0vLeOiYljQWpk+fnhdffDHrr79+8zxjoWNa3FhYeCJj+vTp+eUvf5k//elP+fznP9+8fFV4vyCAttLDDz+cqVOnLvJAkunTpy/22uzVVlst06ZNK6o8VrJvfvOb2XrrrXPggQdmiy22yBe+8IV89rOfzRe+8IXmNsbCquFDH/pQkuTpp59uMf+pp55Kkuaf9fuNh549exoP7dDf/va3jB07Nl/84heT/N/PuWfPni3aLZxe0jhwXGjf3jselpbx0PEszVj43ve+l1KplM9+9rPN84yFjuf9xsKjjz6aTTfdNB/72Mdyxhln5IwzzmhxtnNVeL/gjuZWuuuuu7Lmmmtmm222qXQpVMBFF12UBx98MOedd14GDhyYp556Kpdffnl69uyZo446qtLlUaCNNtooW265ZS666KKss846GThwYO6444789a9/TZJFPs2m/XvjjTdy8sknZ8SIETnssMMqXQ4VZjyw0NKMhdtvvz233HJLLrjggvTt27fgCinKB42FoUOH5rbbbsvMmTPz8MMP57zzzkt1dXUOPPDAClVbPAG0FWbNmpUHHnggBx54YKqrq1ss69mzZ954441F1pk2bdoip9Jpn1544YVce+21ueKKK5rv//3Yxz6WhoaG/PCHP8zBBx+c7t27GwurkAsuuCAnnXRSDj744CTJeuutly9/+csZM2ZM+vTpk2TBsWHmzJmLrDt9+nTjoR2ZPn16jj766PTq1Stjxoxpvs9v4c9wxowZzT/zhe3fvdxxoWN5v/GwtIyHjmNpxsJDDz2Us88+O1/+8pez//77t1hmLHQcSxoL3bt3b/4Kx2222SaNjY254IIL8qlPfSrV1dWrxPsFl+C2wn333Ze5c+e2eFzyQuuvv35eeeWVRb6q4ZVXXmlxrT/t10svvZRkwY3l77bJJptk/vz5efPNN5MYC6uS/v375/bbb88f/vCH3H333bnvvvvSpUuX9OnTJ+utt16SBePh7bffXuTymXHjxhkP7cTcuXNz7LHHZsaMGbnmmmtaXCK18Gf43vtzxo0bl9ra2vTv37+5neNCx/BB42FpGQ8dw9KMhaeeeionnnhiPvnJT+bEE09cZLmx0DG05riw6aabZubMmZk8eXKSVeP9ggDaCr/5zW8yYMCAbL755oss23HHHTNt2rQWX0L/yiuv5Nlnn82OO+5YZJmsJAsDxT//+c8W8//xj3+kVCpl3XXXTWIsrIr69euXDTfcMPX19bnttttaXE6z/fbbp6qqKvfee2/zvGnTpuWPf/yj8dAONDQ05KSTTsq4ceNyzTXXZO21126xvH///hk4cGDuueeeFvPHjh2bbbbZpvkhVY4LHcOSxsPSMh7av6UZCy+99FKOPfbYbL311jnnnHMWux1jof1r7XHh8ccfT/fu3dO7d+8kq8b7BZfg/n9z5szJQw89lCSZOHFiZs6c2fxGYquttmp+tPLkyZPz6KOP5uijj17sdoYPH57tt98+3/jGN/L1r389nTt3ziWXXJLBgwdn9913L+bFsFyWNBY222yzbLbZZvnmN7+Zd955JwMGDMjTTz+dH//4x/n0pz/d/Lh1Y6FjWJpjw4033pju3btnnXXWycSJE3Pdddelc+fOLY4Tffv2zQEHHJALL7wwVVVVWXvttXPVVVelR48ezZfu0nadc845eeCBBzJ69OjMnDmz+SFTyYKrHzp16pQTTjghp556agYMGJARI0Zk7Nixefrpp3PjjTc2t3Vc6BiWZjy89NJLzVfMJAtu37jnnntSV1eXnXbaKYnx0BEsaSzMmDEjRx55ZDp37pzDDz88//jHP5qXd+/ePRtuuGESY6EjWNJYGDduXC666KLsueeeWW+99TJ79uw8+OCDufXWW3PKKaekpmZBLFsV3i+Uyu8917+Keu2117LrrrsudtnPfvazjBgxIknyP//zPzn33HMzduzYbLDBBottP2PGjJx//vm577770tDQkO233z5nnnlmqz8hpVhLMxYmTZqUH/7wh3nkkUfyzjvvpG/fvtlnn31y9NFHp0uXLs3tjYX2b2nGw7XXXpuf//zneeONN9KrV6/svvvuOfHEExe5V2P+/Pm55JJL8qtf/SqzZs3KFltskTPPPPN9jyW0HbvssksmTpy42GV/+MMf0q9fvyTJrbfemquvvjqvv/56Bg0alFNOOSUf//jHW7R3XGj/lmY8jBkzJpdddtkiy9dbb73cf//9zdPGQ/u2pLEwceLE930g0VZbbZUbbrihedpYaN+WNBa6dOmS7373u3nqqacyadKk9OjRI+uvv36OOOKI7Lbbbi3ad/T3CwIoAAAAhXAPKAAAAIUQQAEAACiEAAoAAEAhBFAAAAAKIYACAABQCAEUAACAQgigAAAAFEIABQAAoBACKAAV8/TTT+fggw/OsGHDMnjw4Hz5y1/O4MGDW7TZZZddMnr06ApVuGIdeuihOfTQQytdxhKNGTMmgwcPzuTJkytdCgAdTE2lCwBg1VRfX5+TTjopnTp1yumnn54uXbrkmWeeqXRZq5Qrr7wyG264YXbbbbdKlwLAKkIABaAi/v3vf2fixIk577zzcuCBBzbPe6977rknpVKp6PJWCVdddVX22GMPARSAwgigAFTEwss7e/To8YHtOnXqVEQ5rdbQ0JCmpqY2XycAtAXuAQWgcKNHj84hhxySJDnxxBMzePDg97038r33gN5xxx0ZPHhw/vrXv+bss8/OiBEjssUWW+S0007LtGnTFln32GOPzR//+MeMGjUqQ4YMyV577ZV77713kf1Mnz493/nOd7LTTjtls802yyc+8Yn8+Mc/TlNTU3Ob1157LYMHD85PfvKTXH/99dltt90yZMiQvPzyy63ui/nz5+fSSy/NJz7xiWy22WbZaaedcuGFF2b+/Pkt2g0ePDjnnntufv/732efffbJZpttlr333jsPP/zwItt87LHH8qlPfSpDhgzJbrvtlptuuqn5vs53b2/27Nm58847M3jw4AwePHiRe21nzJiR0aNHZ8stt8xHP/rRnH766ZkzZ84yvb7Ro0dn+PDhef3113Psscdm+PDh2WGHHfI///M/SZLnn38+hx12WIYNG5aPf/zjueuuu1qsv/Dn/be//S3nnXdett5662y55ZY5++yzM3/+/EyfPj2nnXZaPvaxj+VjH/tYLrzwwpTL5WWqEYDiOAMKQOEOOuigrL322rnyyitz6KGHZsiQIVlzzTXzxBNPLPU2zj333PTs2TPHH398XnnllfziF7/I66+/nhtuuKHFJbvjx4/PySefnIMPPjj7779/br/99px44om55pprst122yVJ5syZk0MOOSRvvvlmDj744Kyzzjp58skn8/3vfz+TJk3KGWec0WLfd9xxR+bNm5fPfOYz6dSpU1ZbbbVW9UNTU1O+9KUv5fHHH89nPvOZbLDBBnnhhRfy05/+NOPHj8+PfvSjFu0ff/zx3Hvvvfnc5z6Xbt265YYbbshXv/rVPPDAA+ndu3eS5Nlnn81RRx2VPn365IQTTkhTU1Muv/zyrL766i22deGFF+bMM8/M0KFD85nPfCZJMmDAgBZtTjrppPTr1y+nnHJKnn322dx6661ZffXV81//9V/L9DobGxtz9NFHZ8stt8ypp56au+66K+eee27q6upyySWXZN99983uu++em266KV//+tczbNiw9O/fv8U2zjvvvKy55po54YQT8ve//z0333xzevTokSeffDLrrLNOTj755Dz88MP5yU9+ko022iif/OQnl6lGAIohgAJQuOHDh2f+/Pm58sors+WWW2bPPfdMkmUKoLW1tbn++utTW1ubJFl33XXzve99L/fff3923XXX5nbjx4/PmDFjsvvuuydJDjjggOy555656KKLmgPoddddlwkTJuTOO+/MwIEDkyQHH3xw1lprrfzkJz/JF7/4xayzzjrN23zjjTdy3333LRLqltVdd92VRx55JDfccEO23HLL5vkf/vCH881vfjNPPPFEtthii+b5L7/8csaOHdscFEeMGJFRo0bl7rvvbj6jfOmll6a6ujq/+MUvsvbaaydJRo4cmb322qvFvkeNGpVvfetb6d+/f0aNGrXY+jbeeON897vfbZ6eOnVqbrvttmUOoPPmzct+++2XY489Nkmy7777Zocddsg3vvGNfP/732+ubdttt83IkSPzy1/+MieccEKLbayxxhq5+uqrUyqV8vnPfz7//ve/85Of/CQHHXRQzjnnnCQLPtjYZZddcvvttwugAG2US3ABaJcOOuig5vCZJJ/97GdTU1OThx56qEW7tdZaK5/4xCeap7t3755PfvKTefbZZzNp0qQkCx509NGPfjQ9e/bM5MmTm//bdttt09jYmL/+9a8ttrn77rsvd/hcuN8NNtgg66+/fov9br311kkWXEr7bttuu22Ls5Qf+chH0r1790yYMCHJgjONjz76aHbdddfm8JkkH/rQh7LDDjssc30HH3xwi+ktt9wyU6dOzcyZM5d5WwsfNJUkPXv2zKBBg1JXV5eRI0c2z19//fXTs2fP5tfzbgcccECLM9tDhw5NuVzOAQcc0Dyvuro6m2222WLXB6BtcAYUgHbpQx/6UIvpbt26pU+fPpk4ceIi7d77FN2FZzknTpyYPn365NVXX83zzz+fbbbZZrH7eu/3Yfbr1285q1/g1Vdfzcsvv/y++33nnXdaTL/7LOxCq622WqZPn97cfu7cuYv0TbJofy2Nddddt8V0z549kyTTpk1L9+7dl3o7nTt3XiSw9+jRI3379l3kZ9OjR4/m1/NBtSx8eNV7+6RHjx6L3AsMQNshgAKwymtqasp2222Xo446arHLFwbWhbp06bLC9rvRRhvl9NNPX+zyvn37tpiurq5ebLuV9dCdqqrFXyi1rPt7v7qX5fW8Xy3vNx+AtkkABaBdevXVV5svVU2SWbNmZdKkSdlxxx0XaVculxd5MFGSrLfeekkWPHxn9uzZ2XbbbVd+4e8yYMCA/Otf/8o222yzQr7rdI011kjnzp3z6quvLrJscfMAoGg+NgSgXbr55ptTX1/fPP2LX/wiDQ0NiwTQt956K/fdd1/z9MyZM/PLX/4yG2+8cfr06ZNkwUN6nnzyyfzv//7vIvuZPn16GhoaVsprGDlyZN58883ccsstiyybO3duZs+evUzbq66uzrbbbps//OEPefPNN5vnv/rqq4t9bV27dl3s5a4AsLI4AwpAu1RfX58jjjgiI0eOzCuvvJKf//zn+ehHP9riCbjJgstnzzjjjDzzzDNZY401cvvtt+edd97J+eef39zmyCOPzP3335/jjjsu+++/fzbddNPMmTMnL7zwQn73u9/lD3/4wwp56NB7jRo1Kr/97W/zzW9+M4899li22GKLNDY2Zty4cbnnnntyzTXXZMiQIcu0zeOPPz5//OMf89nPfjaf/exn09TUlBtvvDEf/vCH89xzz7Vou+mmm+bRRx/Nddddl7XWWiv9+vXL5ptvviJfIgC0IIAC0C6dffbZueuuu3LppZemvr4+e++9d84888zFPnDorLPOyoUXXphXXnkl/fr1yyWXXNLiqbB1dXW54YYbctVVV+Wee+7JL3/5y3Tv3j0DBw7MCSec0PzAmxWtqqoql19+ea6//vr86le/yn333Ze6urr069cvhx56aAYNGrTM29xss81y9dVX58ILL8wPf/jDrLPOOvnqV7+acePGZdy4cS3ajh49OmeffXZ+8IMfZO7cudl///0FUABWqlJ5ZT25AABWgjvuuCOnn356brvttiWeHdxll13y4Q9/OFdddVVB1bVdX/7yl/PSSy/l3nvvrXQpAKzC3AMKAB3M3LlzW0yPHz8+Dz/8cLbaaqsKVQQAC7gEFwCW0+TJk9PY2Pi+y2tra9OrV6/C6tltt92y//77p3///pk4cWJuuumm1NbWvu/XzLTGjBkzFgm677XwIU8AsJAACgDL6YADDsjEiRPfd/lWW22VG264obB6dthhh9x9992ZNGlSOnXqlGHDhuWUU05Z5PtMl8d3vvOd3HnnnR/Y5vnnn19h+wOgY3APKAAsp8cffzzz5s173+U9e/bMZpttVmBFK99LL72Ut9566wPbFP29qgC0fQIoAAAAhfAQIgAAAAohgAIAAFAIARQAAIBCCKAAAAAUQgAFAACgEAIoAAAAhRBAAQAAKMT/AxxE6wWCBYrHAAAAAElFTkSuQmCC)
Con el código me dio error en la función del minuto 8:50. Para ello cambié el código a: ```js numeric_columns = processed_penguins_df.select_dtypes(include=[np.number]).columns ( processed_penguins_df[numeric_columns] .quantile(q=[0.75, 0.50, 0.25]) .transpose() .rename_axis('metric') .reset_index() .assign( iqr = lambda df: df[0.75] - df[0.25] ) ) ```

Es interesante esta forma de usar la estadistica descriptiva con los codigos. Al final si fue util llevar ese curso para entender los conceptos y no estar perdido.

Lo que causa esta distribución bimodal de la longitud de las alas de pingüinos es que estamos observando superpuestos los datos de varias especies de pingüinos a la vez. Si tomamos en cuenta la variable de especie, esta distribución se normaliza un poco. ![](https://static.platzi.com/media/user_upload/image-e96b12d6-cf5a-47f2-a2d5-e24aa03b5e17.jpg)
Entre la clase y los comentarios, hay una cantidad sorprendete de buena informacion y cosas por aprender. Este curso es 10/10.

Boxplot:

  • los bigotes deberían de mostrar el límite inferior y superior,
  • la linea de la mitad es la mediana no la media,
  • el rectángulo chico indica más concentración de los valores de los datos y el grande indica mayor dispersión de los valores de los datos,
  • en ambos rectángulos existen la misma cantidad de datos.

 

 

indice = df_num.columns.tolist()
# => indice = ['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g']

# pick me..!
var = indice[2]

# Calcula el IQR para cada columna (para el calculo de los bigotes)
IQR = df_num.quantile(0.75) - df_num.quantile(0.25)

# Cálculo de los límites de los bigotes
lower_limit = df_num.quantile(0.25) - 1.5 * IQR
upper_limit = df_num.quantile(0.75) + 1.5 * IQR

# Ajusta el ancho del gráfico
plt.figure(figsize=(12, 6))

sns.boxplot(
    x=df_num[var]
)

# Línea vertical punteada en la posición de la MEDIANA
plt.axvline(x=df_num[var].median(), 
            color='black', 
            linestyle='dashed', 
            linewidth=1)

# Línea vertical punteada en la posición de la MEDIA
plt.axvline(x=dfnn[var].mean(), 
            color='blue', 
            linestyle='dashed', 
            linewidth=1)

# Línea vertical punteada en la posición del MINIMO
plt.axvline(x=dfnn[var].min(), 
            color='red', 
            linestyle='dashed', 
            linewidth=1)

# Línea vertical punteada en la posición del MAXIMO
plt.axvline(x=dfnn[var].max(), 
            color='red', 
            linestyle='dashed', 
            linewidth=1)

# LIMITE INFERIOR (acá debería llegar el bigote)
plt.axvline(x=lower_limit[var], 
            color='purple', 
            linestyle='--', 
            linewidth=3)

# LIMITE SUPERIOR (acá debería llegar el bigote)
plt.axvline(x=upper_limit[var], 
            color='purple', 
            linestyle='--', 
            linewidth=3)

# Salidas de pantalla
print('\033[95m' + f'Límite inferior -> {lower_limit[var]}' + '\033[0m')
print('\033[91m' + f'Valor mínimo    -> {df_num[var].min()}' + '\033[0m')
print()
print('\033[91m' + f'Valor máximo    -> {df_num[var].max()}' + '\033[0m')
print('\033[95m' + f'Límite superior -> {upper_limit[var]}' + '\033[0m')

plt.show()

![](

Los bins es importante, véanlo como la resolución, a menor longitud de bin, mayor resolución y apreciaremos mejor la distribución e información. Si ya hiciste el hue de colores por especie, ayuda a comprender mejor.

def freedman_diaconis_binwidth(x: pd.Series) -> float:

    IQR = x.quantile(0.75) - x.quantile(0.25)
    N = x.size

    return 2 * IQR / N **(1/3)

sns.histplot(data=processed_penguins_df, x="flipper_length_mm", kde=True, binwidth=freedman_diaconis_binwidth(processed_penguins_df.bill_length_mm));
plt.axvline(x=processed_penguins_df.flipper_length_mm.mean(), color = 'red', linestyle='dashed', linewidth=2)

Me basé en la información compartida por María Eugenia Pereira Chévez para completarlo.

12. Ejercicio de obtención de medidas de dispersión

sns.histplot(
    data=processed_penguins_df, 
    x='bill_depth_mm',
    binwidth=freedman_diaconis_bindwidth(processed_penguins_df['bill_depth_mm'])
    )

mean = processed_penguins_df['bill_depth_mm'].mean()
median = processed_penguins_df['bill_depth_mm'].median()
mode = processed_penguins_df['bill_depth_mm'].mode().values[0]
quantiles = np.percentile(processed_penguins_df['bill_depth_mm'], [25, 50, 75])

plt.axvline(mean, color='red', linestyle='--', linewidth=2, label='Mean')
plt.axvline(median, color='blue', linestyle='--', linewidth=2, label='Median')
plt.axvline(mode, color='green', linestyle='--', linewidth=2, label='Mode')

for i, quantile in enumerate(quantiles):
    plt.axvline(quantile, color='purple', linestyle='--', linewidth=2, label=f'Quantile {i+1}')

plt.legend()
plt.show()
<sns.histplot(
    data = preproced_penguins_df,
    x = "flipper_length_mm",
    hue = "species",
    kde = True,
    bins = 25
)
plt.axvline(
    x = preproced_penguins_df.flipper_length_mm.mean(),
    color = "red",
    ls = "dashed",
    linewidth = 2,
    label = "mean"
    )
plt.axvline(
    x = preproced_penguins_df.flipper_length_mm.median(),
    color = "green",
    ls = "dashed",
    linewidth = 2
)
plt.axvline(
    x = preproced_penguins_df.flipper_length_mm.mode().item(),
    color = "black",
    ls = "dashed",
    linewidth = 2
)
plt.text(201.5,20, "mean", fontsize =12, color = "red")
plt.text(192,20, "median", fontsize =12, color = "green")
plt.text(186,20, "mode", fontsize =12, color = "k")
plt.show()> 

Esta distribución bimodal cuenta con un sesgo positivo ya que cumple la condición “media > mediana > moda”.

El diagrama que tiene 2 picos, para estimarlo, sera necesario utilizar la “estimacion no paramétrica”. Se puede representar como la suma de 2 funciones gaussianas.

Muy buen curso, recomendado!

sns.histplot(df, x='flipper_length_mm')

plt.axvline(x=df['flipper_length_mm'].mean(), color='red', linestyle='dashed',linewidth=2, label='Mean' )

plt.axvline(
    x=df['flipper_length_mm'].median(),
    color='red',
    linestyle='solid',
    linewidth=2,
    label='Median'
)

plt.axvline(
    x=df.flipper_length_mm.mode()[0],
    color='yellow',
    linestyle='solid',
    linewidth=2,
    label='Mode'

)

my_quant = [0.25,0.5,0.75]

for i in my_quant:
    plt.axvline(
        x=df['flipper_length_mm'].quantile(i),
        color='blue',
        linestyle='dashed',
        linewidth=2,
        label=f'Q{int(i/0.25)}'
    )

plt.axvline(
    x=df.flipper_length_mm.max(),
    color='green',
    linestyle='solid',
    linewidth=2,
    label='Max value'

)

plt.axvline(
    x=df.flipper_length_mm.min(),
    color='green',
    linestyle='solid',
    linewidth=2,
    label='Min value'

)

plt.legend()

Ojo: la línea que atraviesa el boxplot en su interior es la mediana, no la media.

OJO, Hay un error conceptual, el cuartil 0.50 NO es la MEDIA, es la MEDIANA.
Pueden comprobarlo con el resultado obtenido al calcular la mediana del dataset.

  • los rangos intercartiles son muchos mas robustos nos dan mas información porque se basan en percentiles


que consiste en dividir nuestros datos en partes iguales

preprossed_penguins_df.quantile()
  • imprimiendo la media de las variables

count      bill_length_mm  bill_depth_mm  flipper_length_mm  body_mass_g
count      342.000000     342.000000         342.000000   342.000000
mean        43.921930      17.151170         200.915205  4201.754386
std          5.459584       1.974793          14.061714   801.954536
min         32.100000      13.100000         172.000000  2700.000000
25%         39.225000      15.600000         190.000000  3550.000000
50%         44.450000      17.300000         197.000000  4050.000000
75%         48.500000      18.700000         213.000000  4750.000000
max         59.600000      21.500000         231.000000  6300.000000

Por ejemplo, podemos ver que la longitud promedio del pico de los pingüinos es de 43,9 mm, con una desviación estándar de 5,5 mm. Esto nos da una idea de la conservación en las medidas de longitud del pico de los pingüinos en nuestro conjunto de datos.

🤔🧠🧑‍🏫👩‍🏫

sns.histplot(x=df.flipper_length_mm,hue=df.species,multiple='stack')

aquí se ve porque se ve esa distribución

Utilizando plotly.graph_objects y plotly.subplots podemos hacer sub gráficos de manera muy detallada, ya que plotly.graph_objects te permite jugar con muchísimos parámetros que puedes cambiar dentro de cada gráfica.

import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots(1,3)

flipper_length_mm = go.Histogram(x=df_limpio.flipper_length_mm, name='Longitud Aleta')
bill_depth_mm = go.Histogram(x=df_limpio.bill_depth_mm, name='Profundidad Pico')
bill_length_mm = go.Histogram(x=df_limpio.bill_length_mm, name='Longitud Pico')

fig.append_trace(flipper_length_mm,1,1)
fig.append_trace(bill_depth_mm,1,2)
fig.append_trace(bill_length_mm,1,3)

fig.update_layout(bargap=0.1)

fig.show()

sns.histplot(
data=processed_penguins_df,
x=‘flipper_length_mm’,
binwidth= freedman_diaconis_bindwidth(preprocess_penguins_df.flipper_length_mm),
kde=True

)
plt.axvline(
x=processed_penguins_df.flipper_length_mm.median(),
color=‘red’,
linestyle=‘dashed’,
linewidth=2

)