Está en la página 1de 12

Agrupamiento K Means: Ejercicio Propuesto

Para este proyecto intentaremos utilizar Agrupamiento K Means para agrupar Universidades en dos grupos, Privado y Público.

Es muy importante tener en cuenta que, de hecho, tenemos las etiquetas para este conjunto de datos, pero NO los utilizaremos para el algoritmo
de agrupamiento de KMeans, ya que es un algoritmo de aprendizaje no supervisado.

Cuando se utiliza el algoritmo Kmeans en circunstancias normales, es porque no tiene etiquetas. En este caso usaremos las etiquetas para tratar de tener
una idea de qué tan bien funcionó el algoritmo, pero generalmente no se tienen estas para Kmeans, por lo que el informe de clasificación y la matriz de
confusión al final de este proyecto no se hacen realmente. ¡tiene sentido en un entorno real!

Los Datos
Utilizaremos un dataframe con 777 observaciones sobre las siguientes 18 variables.

Private Un factor con niveles No y Yes que indica universidad privada o pública
Apps Número de solicitudes recibidas
Accept Número de aplicaciones aceptadas
Enroll Número de nuevos estudiantes matriculados
Top10perc Pct. nuevos estudiantes del 10% superior de H.S.
Top25perc Pct. nuevos estudiantes del 25% superior de H.S.
F.Undergrad Número de estudiantes a tiempo completo
P.Undergrad Número de estudiantes a tiempo parcial
Outstate Matrícula fuera del estado
Room.Board Costos de habitación y comida
Books Costos estimados del libro
Personal Gasto personal estimado
PhD Pct. de la facultad con Ph.D.
Terminal Pct. de la facultad con grado terminal
S.F.Ratio Proporción estudiante / facultad
perc.alumni Pct. ex alumnos que donan
Expend Gastos de instrucción por estudiante
Grad.Rate Tasa de graduación
Importar librerias
** Importe las librerias que generalmente usa para el análisis de datos. **

In [1]: import numpy as np


import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

Obtener los Datos


In [4]: df = pd.read_csv('College_Data', index_col=0)

** Lea en el archivo College_Data usando read_csv. Configure la primera columna como índice.**

In [5]: df.head()

Out[5]:
Private Apps Accept Enroll Top10perc Top25perc F.Undergrad P.Undergrad Outstate Room.Board Books Personal PhD Terminal S.F.Ratio

Abilene
Christian Yes 1660 1232 721 23 52 2885 537 7440 3300 450 2200 70 78 18.1
University

Adelphi
Yes 2186 1924 512 16 29 2683 1227 12280 6450 750 1500 29 30 12.2
University

Adrian
Yes 1428 1097 336 22 50 1036 99 11250 3750 400 1165 53 66 12.9
College

Agnes
Scott Yes 417 349 137 60 89 510 63 12960 5450 450 875 92 97 7.7
College

Alaska
Pacific Yes 193 146 55 16 44 249 869 7560 4120 800 1500 76 72 11.9
University

Revise los primeros registros de los datos


In [6]: df.info()

<class 'pandas.core.frame.DataFrame'>
Index: 777 entries, Abilene Christian University to York College of Pennsylvania
Data columns (total 18 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Private 777 non-null object
1 Apps 777 non-null int64
2 Accept 777 non-null int64
3 Enroll 777 non-null int64
4 Top10perc 777 non-null int64
5 Top25perc 777 non-null int64
6 F.Undergrad 777 non-null int64
7 P.Undergrad 777 non-null int64
8 Outstate 777 non-null int64
9 Room.Board 777 non-null int64
10 Books 777 non-null int64
11 Personal 777 non-null int64
12 PhD 777 non-null int64
13 Terminal 777 non-null int64
14 S.F.Ratio 777 non-null float64
15 perc.alumni 777 non-null int64
16 Expend 777 non-null int64
17 Grad.Rate 777 non-null int64
dtypes: float64(1), int64(16), object(1)
memory usage: 115.3+ KB

** Aplique los métodos info() y describe() en los datos.**


In [7]: df.describe()

Out[7]:
Apps Accept Enroll Top10perc Top25perc F.Undergrad P.Undergrad Outstate Room.Board Books Personal

count 777.000000 777.000000 777.000000 777.000000 777.000000 777.000000 777.000000 777.000000 777.000000 777.000000 777.000000 77

mean 3001.638353 2018.804376 779.972973 27.558559 55.796654 3699.907336 855.298584 10440.669241 4357.526384 549.380952 1340.642214 7

std 3870.201484 2451.113971 929.176190 17.640364 19.804778 4850.420531 1522.431887 4023.016484 1096.696416 165.105360 677.071454 1

min 81.000000 72.000000 35.000000 1.000000 9.000000 139.000000 1.000000 2340.000000 1780.000000 96.000000 250.000000

25% 776.000000 604.000000 242.000000 15.000000 41.000000 992.000000 95.000000 7320.000000 3597.000000 470.000000 850.000000 6

50% 1558.000000 1110.000000 434.000000 23.000000 54.000000 1707.000000 353.000000 9990.000000 4200.000000 500.000000 1200.000000 7

75% 3624.000000 2424.000000 902.000000 35.000000 69.000000 4005.000000 967.000000 12925.000000 5050.000000 600.000000 1700.000000 8

max 48094.000000 26330.000000 6392.000000 96.000000 100.000000 31643.000000 21836.000000 21700.000000 8124.000000 2340.000000 6800.000000 10

Análisis Exploratorio de Datos


¡Es hora de crear algunas visualizaciones de datos!

** Crea un diagrama de dispersión de Grad.Rate vs Room.Board donde los puntos están coloreados por la columna Private. **
In [8]: sns.set(style="darkgrid")
# Crear el diagrama de dispersión con puntos coloreados por la columna Private
plt.figure(figsize=(8, 6))
sns.scatterplot(x="Room.Board", y="Grad.Rate", hue="Private", data=df)
plt.title("Grad.Rate vs Room.Board")
plt.xlabel("Room.Board")
plt.ylabel("Grad.Rate")
plt.show()

Crea un diagrama de dispersión de F.Undergrad vs Outstate donde los puntos están coloreados por la columna Private.
In [9]: sns.set(style="darkgrid")
# Crear el diagrama de dispersión con puntos coloreados por la columna Private
plt.figure(figsize=(8, 6))
sns.scatterplot(x="Outstate", y="F.Undergrad", hue="Private", data=df)
plt.title("F.Undergrad vs Outstate")
plt.xlabel("Outstate")

Out[9]: Text(0.5, 0, 'Outstate')

** Cree un histograma apilado que muestre la matrícula fuera del estado según la columna Private. Intente hacerlo usando sns.FacetGrid
(https://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.FacetGrid.html). Si eso es demasiado complicado, vea si puede hacerlo simplemente
usando dos instancias de pandas.plot(kind='hist'). **
In [34]: sns.set(style="darkgrid")
# Filtrar los datos para universidades privadas y públicas
private_data = df[df["Private"] == "Yes"]
public_data = df[df["Private"] == "No"]
# Crear los histogramas apilados
plt.figure(figsize=(8, 6))
plt.hist(private_data["Outstate"], bins=30, alpha=0.7, label="Private")
plt.hist(public_data["Outstate"], bins=30, alpha=0.7, label="Public")
plt.legend(title="Private")
plt.title("Histograma apilado de matrícula fuera del estado")
plt.xlabel("Outstate")
plt.ylabel("Frecuencia")
plt.show()

Create un histograma similar para la columna Grad.Rate.


In [30]: # Configurar el estilo de las gráficas con Seaborn
sns.set(style="darkgrid")
# Crear el FacetGrid y el histograma apilado
g = sns.FacetGrid(df, hue="Private", height=6)
g.map(sns.histplot, "Grad.Rate", bins=30, alpha=0.7)
g.add_legend(title="Private")
plt.title("Histograma apilado de tasa de graduación")
plt.xlabel("Grad.Rate")
plt.ylabel("Frecuencia")
plt.show()

** Observe cómo parece haber una escuela privada con una tasa de graduación superior al 100%. ¿Cuál es el nombre de esa escuela?**
In [35]: school_data = df[df['Grad.Rate'] > 100]
print(school_data)

Empty DataFrame
Columns: [Private, Apps, Accept, Enroll, Top10perc, Top25perc, F.Undergrad, P.Undergrad, Outstate, Room.Board, Books, Personal,
PhD, Terminal, S.F.Ratio, perc.alumni, Expend, Grad.Rate, Cluster]
Index: []

** Establezca la tasa de graduación de esa escuela en 100, de modo que tenga sentido. Puede obtener una advertencia, no un error, al realizar esta
operación, por lo tanto, utilice las operaciones de dataframe o simplemente vuelva a hacer la visualización del histograma para asegurarse de que realmente
se realizó. **

In [36]: school_index = df[df['Grad.Rate'] > 100].index[0]


df.loc[school_index, 'Grad.Rate'] = 100
sns.set(style="darkgrid")
# Crear el histograma de tasa de graduación
plt.figure(figsize=(8, 6))
sns.histplot(data=df, x="Grad.Rate", hue="Private", bins=30, alpha=0.7)

---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Input In [36], in <cell line: 1>()
----> 1 school_index = df[df['Grad.Rate'] > 100].index[0]
2 df.loc[school_index, 'Grad.Rate'] = 100
3 sns.set(style="darkgrid")

File ~\anaconda3\lib\site-packages\pandas\core\indexes\base.py:5039, in Index.__getitem__(self, key)


5036 if is_integer(key) or is_float(key):
5037 # GH#44051 exclude bool, which would return a 2d ndarray
5038 key = com.cast_scalar_indexer(key, warn_float=True)
-> 5039 return getitem(key)
5041 if isinstance(key, slice):
5042 # This case is separated from the conditional above to avoid
5043 # pessimization com.is_bool_indexer and ndim checks.
5044 result = getitem(key)

IndexError: index 0 is out of bounds for axis 0 with size 0

In [29]: ​

Out[29]: Private Apps Accept Enroll Top10perc Top25perc F.Undergrad P.Undergrad Outstate Room.Board Books Personal PhD Terminal S.F.Ratio perc.alum
In [30]: ​

Out[30]: <matplotlib.legend.Legend at 0x1a112c12da0>

Creación del clúster K Means


¡Ahora es el momento de crear las etiquetas del Cluster!

** Importar KMeans de SciKit Learn. **

In [20]: from sklearn.cluster import KMeans

** Crea una instancia de un modelo de KM eans con 2 clústeres. **

In [21]: kmeans = KMeans(n_clusters=2)

** Ajuste el modelo a todos los datos a excepción de la etiqueta Private. **

In [22]: kmeans.fit(df.drop('Private', axis=1))

Out[22]: KMeans(n_clusters=2)

** ¿Cuáles son los centro del grupo de los vectores? **


In [23]: centroids = kmeans.cluster_centers_
print(centroids)

[[1.03631389e+04 6.55089815e+03 2.56972222e+03 4.14907407e+01


7.02037037e+01 1.30619352e+04 2.46486111e+03 1.07191759e+04
4.64347222e+03 5.95212963e+02 1.71420370e+03 8.63981481e+01
9.13333333e+01 1.40277778e+01 2.00740741e+01 1.41705000e+04
6.75925926e+01]
[1.81323468e+03 1.28716592e+03 4.91044843e+02 2.53094170e+01
5.34708520e+01 2.18854858e+03 5.95458894e+02 1.03957085e+04
4.31136472e+03 5.41982063e+02 1.28033632e+03 7.04424514e+01
7.78251121e+01 1.40997010e+01 2.31748879e+01 8.93204634e+03
6.50926756e+01]]

Evaluación
No existe una forma perfecta de evaluar la agrupación si no se cuenta con las etiquetas, sin embargo, dado que se trata de un ejercicio y sí tenemos las
etiquetas, por lo que aprovechamos esto para evaluar nuestros grupos, tenga en cuenta que generalmente no es así en el mundo real.

** Cree una nueva columna para df llamada 'Cluster', que es un 1 para una escuela privada y un 0 para una escuela pública. **

In [24]: df['Cluster'] = df['Private'].apply(lambda x: 1 if x == 'Yes' else 0)

In [25]: df.head()

Out[25]:
Private Apps Accept Enroll Top10perc Top25perc F.Undergrad P.Undergrad Outstate Room.Board Books Personal PhD Terminal S.F.Ratio

Abilene
Christian Yes 1660 1232 721 23 52 2885 537 7440 3300 450 2200 70 78 18.1
University

Adelphi
Yes 2186 1924 512 16 29 2683 1227 12280 6450 750 1500 29 30 12.2
University

Adrian
Yes 1428 1097 336 22 50 1036 99 11250 3750 400 1165 53 66 12.9
College

Agnes
Scott Yes 417 349 137 60 89 510 63 12960 5450 450 875 92 97 7.7
College

Alaska
Pacific Yes 193 146 55 16 44 249 869 7560 4120 800 1500 76 72 11.9
University
** Cree una matriz de confusión y un informe de clasificación para ver qué tan bien funcionó el clúster de K Means sin etiquetas. **

In [26]: from sklearn.metrics import confusion_matrix, classification_report


confusion_mat = confusion_matrix(df['Cluster'], kmeans.labels_)
classification_rep = classification_report(df['Cluster'], kmeans.labels_)
print("Matriz de Confusión:")
print(confusion_mat)
print("\nInforme de Clasificación:")
print(classification_rep)

Matriz de Confusión:
[[ 74 138]
[ 34 531]]

Informe de Clasificación:
precision recall f1-score support

0 0.69 0.35 0.46 212


1 0.79 0.94 0.86 565

accuracy 0.78 777


macro avg 0.74 0.64 0.66 777
weighted avg 0.76 0.78 0.75 777

¡No está mal teniendo en cuenta que el algoritmo está utilizando puramente las características para agrupar las universidades en 2 grupos distintos! ¡Con
suerte, puede comenzar a ver cómo K Means es útil para agrupar datos no etiquetados!

Great Job!

También podría gustarte