Skip to content

Alt text source: @allison_horst https://github.com/allisonhorst/penguins

You have been asked to support a team of researchers who have been collecting data about penguins in Antartica! The data is available in csv-Format as penguins.csv

Origin of this data : Data were collected and made available by Dr. Kristen Gorman and the Palmer Station, Antarctica LTER, a member of the Long Term Ecological Research Network.

The dataset consists of 5 columns.

ColumnDescription
culmen_length_mmculmen length (mm)
culmen_depth_mmculmen depth (mm)
flipper_length_mmflipper length (mm)
body_mass_gbody mass (g)
sexpenguin sex

Unfortunately, they have not been able to record the species of penguin, but they know that there are at least three species that are native to the region: Adelie, Chinstrap, and Gentoo. Your task is to apply your data science skills to help them identify groups in the dataset!

# Import Required Packages
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# Loading and examining the dataset
penguins_df = pd.read_csv("penguins.csv")
penguins_df.head()
# Importar las bibliotecas necesarias
import pandas as pd  # Para manejar datos tabulares
import matplotlib.pyplot as plt  # Para la visualización de datos
from sklearn.cluster import KMeans  # Algoritmo de clustering
from sklearn.preprocessing import StandardScaler  # Para normalizar los datos

# Cargar el dataset
# El archivo "penguins.csv" debe estar en el mismo directorio que este script o especificar la ruta completa
penguins_df = pd.read_csv("penguins.csv")

# Visualizar las primeras filas del dataset para entender su estructura
print(penguins_df.head())

# ----------------------
# ETAPA 1: Exploración de los datos
# ----------------------

# Verificar si hay valores faltantes en el dataset
print(penguins_df.isnull().sum())

# Verificar los tipos de datos para identificar columnas categóricas o no numéricas
print(penguins_df.dtypes)
# Define the numeric_columns variable
numeric_columns = penguins_df.select_dtypes(include=['number']).columns

# Now print the sum of null values in numeric columns
print(penguins_df[numeric_columns].isnull().sum())
print(penguins_df[numeric_columns].dtypes)
penguins_df = pd.read_csv("penguins.csv")
print(penguins_df[numeric_columns].head())
# Confirmar que solo trabajamos con las columnas numéricas
numeric_columns = ['culmen_length_mm', 'culmen_depth_mm', 'flipper_length_mm', 'body_mass_g']
data_to_scale = penguins_df[numeric_columns]

# Verificar que no haya valores inesperados (nan o inf)
print("Verificando valores inesperados en los datos numéricos:")
print(data_to_scale.describe())  # Estadísticas para verificar posibles anomalías
print(data_to_scale.isin([float('inf'), float('-inf')]).sum())  # Valores infinitos

# Normalizar los datos con StandardScaler
try:
    scaler = StandardScaler()
    penguins_df[numeric_columns] = scaler.fit_transform(data_to_scale)
    print("Normalización completada con éxito. Ejemplo de datos normalizados:")
    print(penguins_df.head())
except ValueError as e:
    print("Error durante la normalización:", e)
# ----------------------
# ETAPA 3: Aplicar K-means Clustering
# ----------------------

from sklearn.cluster import KMeans

# Inicializar el algoritmo K-means con 3 clusters
kmeans = KMeans(n_clusters=3, random_state=0)

# Ajustar el modelo a los datos normalizados y predecir los clusters
penguins_df['cluster'] = kmeans.fit_predict(penguins_df[numeric_columns])

# Verificar los primeros resultados: etiquetas de cluster asignadas
print("Ejemplo de datos con clusters asignados:")
print(penguins_df.head())
# ----------------------
# ETAPA 4: Análisis de los clusters
# ----------------------

# Agrupar los datos por cluster y calcular las medias de cada variable
stat_penguins = penguins_df.groupby('cluster').mean()

# Eliminar columnas no numéricas del análisis (si las hay)
stat_penguins = stat_penguins.drop(columns=['sex'], errors='ignore')

# Mostrar el DataFrame final con estadísticas de cada cluster
print("Estadísticas promedio por cluster:")
print(stat_penguins)
import matplotlib.pyplot as plt

# Visualizar los clusters en un espacio bidimensional (culmen_length_mm vs culmen_depth_mm)
plt.figure(figsize=(8, 6))
scatter = plt.scatter(
    penguins_df['culmen_length_mm'], 
    penguins_df['culmen_depth_mm'], 
    c=penguins_df['cluster'], 
    cmap='viridis', 
    alpha=0.7
)

# Configuración del gráfico
plt.title('Visualización de Clusters: Longitud vs Profundidad del Culmen')
plt.xlabel('Culmen Length (normalizado)')
plt.ylabel('Culmen Depth (normalizado)')
plt.colorbar(scatter, label='Cluster')
plt.grid(True)
plt.show()
from sklearn.metrics import silhouette_score

# Asegurarse de que las columnas numéricas existen
numeric_columns = ['culmen_length_mm', 'culmen_depth_mm', 'flipper_length_mm', 'body_mass_g']
if all(col in penguins_df.columns for col in numeric_columns):
    # Evaluar diferentes números de clusters
    for n in range(2, 6):  # Probar con 2, 3, 4 y 5 clusters
        kmeans = KMeans(n_clusters=n, random_state=0)
        labels = kmeans.fit_predict(penguins_df[numeric_columns])
        sil_score = silhouette_score(penguins_df[numeric_columns], labels)
        print(f"Clusters: {n}, Silhouette Score: {sil_score:.3f}")

    # Mostrar el Silhouette Score final
    print(f"Silhouette Score (última iteración): {sil_score:.3f}")
    print(f"Inercia (distancias intra-cluster): {kmeans.inertia_:.3f}")
else:
    print("Error: Algunas columnas en numeric_columns no están disponibles en penguins_df.")
# Asegurarnos de que tenemos los valores originales
# (si modificaste directamente los originales en penguins_df, recarga el dataset)
original_df = pd.read_csv("penguins.csv")

# Reasignar los clusters al DataFrame original basado en los clusters calculados previamente
original_df['cluster'] = penguins_df['cluster']  # Etiquetas de cluster ya calculadas

# Crear el DataFrame `stat_penguins` con las medias de las variables numéricas por cluster
numeric_columns = ['culmen_length_mm', 'culmen_depth_mm', 'flipper_length_mm', 'body_mass_g']
stat_penguins = original_df.groupby('cluster')[numeric_columns].mean()

# Mostrar el resultado final
print("DataFrame final (stat_penguins):")
print(stat_penguins)