Skip to content

Instantly share code, notes, and snippets.

@adraguidev
Last active August 10, 2020 04:40
Show Gist options
  • Save adraguidev/64845c2fdac80658992b4bf1963cdc1a to your computer and use it in GitHub Desktop.
Save adraguidev/64845c2fdac80658992b4bf1963cdc1a to your computer and use it in GitHub Desktop.
Metodo Jerarquico
import pandas as pd
import numpy as np
np.random.seed(123) #generamos semilla
variables = ['X', 'Y', 'Z'] #variables
labels = ['ID_0', 'ID_1', 'ID_2', 'ID_3', 'ID_4'] #valores
X = np.random.random_sample([5, 3])*10 #Le damos valores
df = pd.DataFrame(X, columns=variables, index=labels) #Creamos nuestro dataframe aleatorio
##Realizamos agrupamiento jerarquico sobre una matriz de distancia##
from scipy.spatial.distance import pdist, squareform #importamos librerias
#creamos un dataframe con las distancias euclidianas entre las etiquetas
row_dist = pd.Dataframe(squareform(pdist(df,metric='euclidean')),
columns=labels,
index=labels)
row_dist
#Podemos pasar una matriz de distancia condensed (triangular superior) desde la función pdist, o podemos pasar la matriz de datos "original" y definir el argumentometric = 'euclidean' #en linkage. Sin embargo, no deberíamos pasar la matriz de distancia de forma cuadrada, que produciría diferentes valores de distancia, aunque la agrupación general podría ser la misma.
# 2. enfoque correcto: matriz de distancia condensed (condensada)
row_clusters = linkage(pdist(df, metric='euclidean'), method='complete')
pd.DataFrame(row_clusters,
columns=['row label 1', 'row label 2',
'distance', 'no. of items in clust.'],
index=['cluster %d' % (i + 1)
for i in range(row_clusters.shape[0])])
# 3. enfoque correcto: matriz de muestra imput
row_clusters = linkage(df.values, method='complete', metric='euclidean')
pd.DataFrame(row_clusters,
columns=['row label 1', 'row label 2',
'distance', 'no. of items in clust.'],
index=['cluster %d' % (i + 1)
for i in range(row_clusters.shape[0])])
##Dendograma en un mapa de calor:
# dendograma de fila
fig = plt.figure(figsize=(8, 8), facecolor='white')
axd = fig.add_axes([0.09, 0.1, 0.2, 0.6])
# nota: for matplotlib < v1.5.1, usar orientation='right'
row_dendr = dendrogram(row_clusters, orientation='left')
# reordenar datos con respecto a la aplicación
df_rowclust = df.iloc[row_dendr['leaves'][::-1]]
axd.set_xticks([])
axd.set_yticks([])
# remover eje del dendograma
for i in axd.spines.values():
i.set_visible(False)
# mapa de calor
axm = fig.add_axes([0.23, 0.1, 0.6, 0.6]) # x-pos, y-pos, width, height
cax = axm.matshow(df_rowclust, interpolation='nearest', cmap='hot_r')
fig.colorbar(cax)
axm.set_xticklabels([''] + list(df_rowclust.columns))
axm.set_yticklabels([''] + list(df_rowclust.index))
#plt.savefig('images/11_12.png', dpi=300)
plt.show()
from sklearn.cluster import AgglomerativeClustering
X
ac = AgglomerativeClustering(n_clusters=3, #numero de clusters
affinity='euclidean', #metrica de distancia
linkage='complete') #metodo de enlace
labels = ac.fit_predict(X) #fit_predict()
print('Cluster labels: %s' % labels)
ac = AgglomerativeClustering(n_clusters=2,
affinity='euclidean',
linkage='complete')
labels = ac.fit_predict(X)
print('Cluster labels: %s' % labels)
import pandas as pd
import pyreadstat
filesav = 'datos/distritos.sav'
df, meta = pyreadstat.read_sav(filesav )
meta
df.head()
# Clustering Jerárquico
# Importacion de librerias
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
X = df.iloc[:, 1:].values
X
# Creamos el dendograma para encontrar el número óptimo de clusters
import scipy.cluster.hierarchy as sch
dendrogram = sch.dendrogram(sch.linkage(X, method = 'ward'))
plt.title('Dendograma')
plt.xlabel('Distritos')
plt.ylabel('Distancias Euclidianas')
plt.show()
# Ajustando Clustering Jerárquico al conjunto de datos
from sklearn.cluster import AgglomerativeClustering
hc = AgglomerativeClustering(n_clusters = 2,
affinity = 'euclidean',
linkage = 'ward')
y_hc = hc.fit_predict(X)
y_hc
""" **affinity:** por defecto es "euclidean". Puede adoptar: “euclidean”, “l1”, “l2”, “manhattan”, “cosine”, o “precomputed”.
Si el enlace es "ward", solo se acepta "euclidian". Si está "precomputed", se necesita una matriz de distancia (en lugar de una matriz de similitud) como entrada para el método de ajuste. """
""" **linkage:** enlace predeterminado es ward.
Qué criterio de vinculación utilizar. El criterio de vinculación determina qué distancia usar entre conjuntos de observación. El algoritmo fusionará los pares de clúster que minimizan este criterio.
- Ward minimiza la varianza de los grupos que se fusionan.
- promedio (average) usa el promedio de las distancias de cada observación de los dos conjuntos.
- el enlace completo (complete) o máximo (maximum) utiliza las distancias máximas entre todas las observaciones de los dos conjuntos.
- single usa el mínimo de las distancias entre todas las observaciones de los dos conjuntos. """
type(y_hc)
cl= pd.DataFrame(y_hc, columns=["clúster_ward"])
cl.head()
distritos_new = pd.concat([df, cl], axis=1)
distritos_new
#Predicción de agrupamiento
agg_clust = AgglomerativeClustering(n_clusters=2)
assigned_clust = agg_clust.fit_predict(X)
assigned_clust
plt.scatter(X[:, 2], X[:, 3], c = assigned_clust, s = 30);
#Numero optimo de cluster
from sklearn.metrics import euclidean_distances, silhouette_score
s = []
for n_clusters in range(2,10):
hc = AgglomerativeClustering(n_clusters = n_clusters,
affinity = 'euclidean',
linkage = 'ward')
hc.fit(X)
#labels = hc.fit_predict(X)
#centroids = kmeans.cluster_centers_
s.append(silhouette_score(X, hc.fit_predict(X)))
plt.plot(range(2,10), s)
plt.ylabel("Silouette")
plt.xlabel("k")
plt.title("Silouette para data distritos")
#sns.despine()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment