1
votes

From research, only Single-Linkage Hierarchical Clustering can obtain optimal clusters. This is also know as SLINK. The libraries are published in originally in C++ and now in Python/R.

So far, following the steps in the documentations, I managed to come up with:

import pandas as pd
from scipy.cluster.hierarchy import dendrogram, linkage
from scipy.spatial.distance import pdist

## generating random numbers from 20 to 90, and storing them in a dataframe. This is a 1-dimensional data
np.random.seed(1)
df = pd.DataFrame(np.random.randint(20,90,size=(100,1)), columns = list('A'))
df = df.sort_values(by=['A'])
df = df.values
df[:,0].sort()

## getting condensed distance matrix
d = pdist(df_final, metric='euclidean')

## running the SLINK algorithm
Z = linkage(d, 'single')

I understand that Z is a 'hierarchical clustering encoded as a linkage matrix' (as written in the documentation), but I am wondering how do I go back to my original data set and distinguish the cluster calculated by this result?

I could achieve clustering result by Scikit-Learn clustering, but I think Scikit-Learn clustering algorithms are not optimal and hence I turned to this SLINK algorithm. Would be much appreciated if someone could help me with this.

1

1 Answers

2
votes

From scipy.cluster.hierarchy.linkage you get back how clusters are formed with each iteration.

Normally this information is not so useful, so we can look at the clustering first:

import scipy as scipy
import matplotlib.pyplot as plt
plt.figure()
dn =scipy.cluster.hierarchy.dendrogram(Z)

enter image description here

If we want to get the three clusters, we can do:

labels = scipy.cluster.hierarchy.fcluster(Z,3,'maxclust')

If you want to get it by distance between the data points:

scipy.cluster.hierarchy.fcluster(Z,2,'distance')

This gives about the same result as calling for 3 clusters because that's not many ways to cut this example dataset.

If you look the example you have, the next point you can cut it is at height ~ 1.5, which is 16 clusters. So if you try to do scipy.cluster.hierarchy.fcluster(Z,5,'maxclust'), you get the same results as for 3 clusters. If you have a more spread dataset, it will work:

np.random.seed(111)
df = np.random.normal(0,1,(50,3))

## getting condensed distance matrix
d = pdist(df, metric='euclidean')
Z = linkage(d, 'single')
dn = scipy.cluster.hierarchy.dendrogram(Z,above_threshold_color='black',color_threshold=1.1)

enter image description here

Then this works:

scipy.cluster.hierarchy.fcluster(Z,5,'maxclust')