Package: clustergram
ClustergramVisualization and diagnostics for cluster analysisClustergram is a diagram proposed by Matthias Schonlau in his paperThe clustergram: A
graph for visualizing hierarchical and nonhierarchical cluster
analyses:In hierarchical cluster analysis, dendrograms are used to visualize how clusters are
formed. I propose an alternative graph called a “clustergram” to examine how cluster
members are assigned to clusters as the number of clusters increases. This graph is
useful in exploratory analysis for nonhierarchical clustering algorithms such as
k-means and for hierarchical cluster algorithms when the number of observations is
large enough to make dendrograms impractical.The clustergram was later implemented in R byTal
Galili,
who also gives a thorough explanation of the concept.This is a Python implementation, originally based on Tal's script, written forscikit-learnand RAPIDScuMLimplementations of K-Means, Mini Batch K-Means and
Gaussian Mixture Model (scikit-learn only) clustering, plus hierarchical/agglomerative
clustering usingSciPy. Alternatively, you can create clustergram usingfrom_*constructors based on alternative clustering algorithms.Getting startedYou can install clustergram fromcondaorpip:condainstallclustergram-cconda-forgepipinstallclustergramIn any case, you still need to install your selected backend (scikit-learnandscipyorcuML).The example of clustergram on Palmer penguins dataset:importseaborndf=seaborn.load_dataset('penguins')First we have to select numerical data and scale them.fromsklearn.preprocessingimportscaledata=scale(df.drop(columns=['species','island','sex']).dropna())And then we can simply pass the data toclustergram.fromclustergramimportClustergramcgram=Clustergram(range(1,8))cgram.fit(data)cgram.plot()StylingClustergram.plot()returns matplotlib axis and can be fully customised as any other
matplotlib plot.seaborn.set(style='whitegrid')cgram.plot(ax=ax,size=0.5,linewidth=0.5,cluster_style={"color":"lightblue","edgecolor":"black"},line_style={"color":"red","linestyle":"-."},figsize=(12,8))Mean optionsOn theyaxis, a clustergram can use mean values as in the original paper by Matthias
Schonlau or PCA weighted mean values as in the implementation by Tal Galili.cgram=Clustergram(range(1,8))cgram.fit(data)cgram.plot(figsize=(12,8),pca_weighted=True)cgram=Clustergram(range(1,8))cgram.fit(data)cgram.plot(figsize=(12,8),pca_weighted=False)Scikit-learn, SciPy and RAPIDS cuML backendsClustergram offers three backends for the computation -scikit-learnandscipywhich
use CPU and RAPIDS.AIcuML, which uses GPU. Note that all are optional dependencies
but you will need at least one of them to generate clustergram.Usingscikit-learn(default):cgram=Clustergram(range(1,8),backend='sklearn')cgram.fit(data)cgram.plot()UsingcuML:cgram=Clustergram(range(1,8),backend='cuML')cgram.fit(data)cgram.plot()datacan be all data types supported by the selected backend (includingcudf.DataFramewithcuMLbackend).Supported methodsClustergram currently supports K-Means, Mini Batch K-Means, Gaussian Mixture Model and
SciPy's hierarchical clustering methods. Note tha GMM and Mini Batch K-Means are
supported only forscikit-learnbackend and hierarchical methods are supported only
forscipybackend.Using K-Means (default):cgram=Clustergram(range(1,8),method='kmeans')cgram.fit(data)cgram.plot()Using Mini Batch K-Means, which can provide significant speedup over K-Means:cgram=Clustergram(range(1,8),method='minibatchkmeans',batch_size=100)cgram.fit(data)cgram.plot()Using Gaussian Mixture Model:cgram=Clustergram(range(1,8),method='gmm')cgram.fit(data)cgram.plot()Using Ward's hierarchical clustering:cgram=Clustergram(range(1,8),method='hierarchical',linkage='ward')cgram.fit(data)cgram.plot()Manual inputAlternatively, you can create clustergram usingfrom_dataorfrom_centersmethods
based on alternative clustering algorithms.UsingClustergram.from_datawhich creates cluster centers as mean or median values:data=numpy.array([[-1,-1,0,10],[1,1,10,2],[0,0,20,4]])labels=pandas.DataFrame({1:[0,0,0],2:[0,0,1],3:[0,2,1]})cgram=Clustergram.from_data(data,labels)cgram.plot()UsingClustergram.from_centersbased on explicit cluster centers.:labels=pandas.DataFrame({1:[0,0,0],2:[0,0,1],3:[0,2,1]})centers={1:np.array([[0,0]]),2:np.array([[-1,-1],[1,1]]),3:np.array([[-1,-1],[1,1],[0,0]]),}cgram=Clustergram.from_centers(centers,labels)cgram.plot(pca_weighted=False)To support PCA weighted plots you also need to pass data:cgram=Clustergram.from_centers(centers,labels,data=data)cgram.plot()Partial plotClustergram.plot()can also plot only a part of the diagram, if you want to focus on a
limited range ofk.cgram=Clustergram(range(1,20))cgram.fit(data)cgram.plot(figsize=(12,8))cgram.plot(k_range=range(3,10),figsize=(12,8))Additional clustering performance evaluationClustergam includes handy wrappers around a selection of clustering performance metrics
offered byscikit-learn. Data which were originally computed on GPU are converted to
numpy on the fly.Silhouette scoreCompute the mean Silhouette Coefficient of all samples. Seescikit-learndocumentationfor details.>>>cgram.silhouette_score()20.53154030.44721940.40015450.37772060.37212870.331575Name:silhouette_score,dtype:float64Once computed, the resulting Series is available ascgram.silhouette_. Calling the original
method will recompute the score.Calinski and Harabasz scoreCompute the Calinski and Harabasz score, also known as the Variance Ratio Criterion. Seescikit-learndocumentationfor details.>>>cgram.calinski_harabasz_score()2482.1914693441.6770754400.3921315411.1750666382.7314167352.447569Name:calinski_harabasz_score,dtype:float64Once computed, the resulting Series is available ascgram.calinski_harabasz_. Calling the
original method will recompute the score.Davies-Bouldin scoreCompute the Davies-Bouldin score. Seescikit-learndocumentationfor details.>>>cgram.davies_bouldin_score()20.71406430.94355340.94332050.97324860.95091071.074937Name:davies_bouldin_score,dtype:float64Once computed, the resulting Series is available ascgram.davies_bouldin_. Calling the
original method will recompute the score.Accessing labelsClustergramstores resulting labels for each of the tested options, which can be
accessed as:>>>cgram.labels_12345670002232110022321200223213002232140022003................33701132503380113250339011111434001132553410111115Saving clustergramYou can save both the plot andclustergram.Clustergramto a disk.Saving plotClustergram.plot()returns matplotlib axis object and as such can be saved as any
other plot:importmatplotlib.pyplotaspltcgram.plot()plt.savefig('clustergram.svg')Saving objectIf you want to save your computedclustergram.Clustergramobject to a disk, you can
usepicklelibrary:importpicklewithopen('clustergram.pickle','wb')asf:pickle.dump(cgram,f)Then loading is equally simple:withopen('clustergram.pickle','rb')asf:loaded=pickle.load(f)ReferencesSchonlau M. The clustergram: a graph for visualizing hierarchical and non-hierarchical
cluster analyses. The Stata Journal, 2002; 2 (4):391-402.Schonlau M. Visualizing Hierarchical and Non-Hierarchical Cluster Analyses with
Clustergrams. Computational Statistics: 2004; 19(1):95-111.https://www.r-statistics.com/2010/06/clustergram-visualization-and-diagnostics-for-cluster-analysis-r-code/