Capítulo 29 Árboles.

Recuérdese que los árboles son una sub-clasificación de las redes, en donde no hay ciclos, son direccionales y jerárquicas.

Se requiere el uso del módulo scipy.

Sea leída una base de datos de la administración de una gran superficie o “Mall”.

import matplotlib.pyplot as plt
import pandas as pd
import scipy
import numpy as np
df = pd.read_csv(data_dir/"Mall_Customers.csv")
df.head()
##    ClienteID       Sexo  ...  Ingresos mensuales(miles)  Indice de gasto (1-100)
## 0          1  Masculino  ...                         15                       39
## 1          2  Masculino  ...                         15                       81
## 2          3   Femenino  ...                         16                        6
## 3          4   Femenino  ...                         16                       77
## 4          5   Femenino  ...                         17                       40
## 
## [5 rows x 5 columns]
df.columns
## Index(['ClienteID', 'Sexo', 'Edad', 'Ingresos mensuales(miles)',
##        'Indice de gasto (1-100)'],
##       dtype='object')

La base de datos presenta para un conjunto de clientes su sexo, edad, nivel de ingresos y un índice de gastos. Desconocemos cómo se generó dicho índice. Debemos suponer que hace referencia a qué monto gasta en el Mall.

Suponga se desea categorizar a los clientes del Mall mediante un algoritmo de conglomerados.

La función linkage del módulo scipy.cluster.hierarchy realiza lo que se denomina un agrupamiento (clustering) jerárquico.

La entrada y puede ser una matriz de distancias ya calculadas, o una matriz (2-D) de vectores de observación, de tal manera que internamente calcule las distancias.

Al correr el algoritmo, éste devuelve una matriz Z de 4 en 4. Los datos del vector de observación son las dos primera scolumnas Z[i, 0] y Z[i, 1]. La distancia viene dada por Z[i, 2]. El cuarto valor, Z[i, 3], representa el número de observaciones en el clúster recién formado.

Para la visualización del resultado nos interesan las columnas tercera y cuarta

X = df.iloc[:, [3, 4]].values
X.shape
## (200, 2)

Obsérvese el resultado de realizar el agrupamiento:

import scipy.cluster.hierarchy as sch
grupos = sch.linkage(X, method = 'ward')
# convert the array to a DataFrame and add column headers
df = pd.DataFrame(grupos, columns=['Grupo_1', 'Grupo_2', 'Distancia', 'N.puntos'])
# show the first 10 rows of the DataFrame
print(df.head(10))
##    Grupo_1  Grupo_2  Distancia  N.puntos
## 0     65.0     68.0        0.0       2.0
## 1     48.0     49.0        0.0       2.0
## 2    156.0    158.0        0.0       2.0
## 3    129.0    131.0        0.0       2.0
## 4     21.0     23.0        1.0       2.0
## 5     51.0     53.0        1.0       2.0
## 6     60.0     61.0        1.0       2.0
## 7     67.0     69.0        1.0       2.0
## 8     64.0     66.0        1.0       2.0
## 9     79.0     82.0        1.0       2.0
print(df.tail(10))
##      Grupo_1  Grupo_2   Distancia  N.puntos
## 189    352.0    382.0   64.537406      49.0
## 190    371.0    385.0   69.523155      30.0
## 191    377.0    381.0   81.179359      23.0
## 192    383.0    389.0  106.650579      85.0
## 193    388.0    390.0  112.818203      39.0
## 194    384.0    386.0  113.886017      32.0
## 195    391.0    392.0  245.654601     108.0
## 196    387.0    395.0  262.562634     129.0
## 197    393.0    394.0  394.859658      71.0
## 198    396.0    397.0  405.660041     200.0

Para la visualización se aplica el método dendogram:

dendrogram = sch.dendrogram(grupos)
plt.title('Dendograma')
## Text(0.5, 1.0, 'Dendograma')
plt.xlabel('Clientes')
## Text(0.5, 0, 'Clientes')
plt.ylabel('Agrupamiento')
## Text(0, 0.5, 'Agrupamiento')
plt.show()

Se puede ensanchar para mejorar la visualización:

fig, ax = plt.subplots(figsize=(20, 10))
dendrogram = sch.dendrogram(grupos, ax=ax, leaf_font_size=10)
plt.title('Dendograma')
## Text(0.5, 1.0, 'Dendograma')
plt.ylabel('Clientes')
## Text(0, 0.5, 'Clientes')
plt.xlabel('Agrupamiento')
## Text(0.5, 0, 'Agrupamiento')

Como en toda visualización con muchas categorías, intercambiar los ejes x y y mejora la visibilidad siempre y cuando sea de interés identificar las hojas de cada grupo, en cuyo caso habrá que jugar con el alto del lienzo y el tamaño de las etiquetas del eje:

fig, ax = plt.subplots(figsize=(10, 26))
dendrogram = sch.dendrogram(grupos, ax=ax, leaf_font_size=8, orientation='right')
plt.title('Dendograma')
## Text(0.5, 1.0, 'Dendograma')
plt.xlabel('Clientes')
## Text(0.5, 0, 'Clientes')
plt.ylabel('Agrupamiento')
## Text(0, 0.5, 'Agrupamiento')