Get element closest to cluster centroid
<p>After clustering a distance matrix with <code>scipy.cluster.hierarchy.linkage</code>, and assigning each sample to a cluster using <code>scipy.cluster.hierarchy.cut_tree</code>, I would like to extract one element out of each cluster, which is the closest to that cluster's centroid.</p>

<ul>
<li>I would be the happiest if an off-the-shelf function existed for this, but in the lack thereof:</li>
<li>some suggestions were already proposed <a href="http://stackoverflow.com/questions/9362304/how-to-get-centroids-from-scipys-hierarchical-agglomerative-clustering">here</a> for extracting the centroids themselves, but not the closest-to-centroid elements.</li>
<li>Note that this is not to be confused with the <code>centroid</code> linkage rule in <code>scipy.cluster.hierarchy.linkage</code>. I have already carried out the clustering itself, just want to access the closest-to-centroid elements.</li>
</ul>

<p><a href="http://stackoverflow.com/users/2912349/paul">Paul</a>'s solution above works well for multidimensional arrays. In the more specific case, where you have a distance matrix <code>dm</code>, in which the distances are calculated in a "non-trivial" way (<em>e.g.</em> each pair objects is aligned in 3D first, then RMSD is calculated), I ended up selecting from each cluster the element whose sum of distances to the other elements in the cluster is the lowest. (See discussion below <a href="http://stackoverflow.com/a/39767308/6869965">this</a> answer.) This is how I did it in possession of the distance matrix <code>dm</code> and the list of object names in identical order <code>names</code>:</p>

<pre><code>import numpy as np
import scipy.spatial.distance as spd
import scipy.cluster.hierarchy as sch

# Square form of distance matrix
sq=spd.squareform(dm)
# Perform clustering, capture linkage object
clusters=sch.linkage(dm,method=linkage)
# List of cluster assignments
assignments=sch.cut_tree(clusters,height=rmsd_cutoff)
# Store object names and assignments as zip object (list of tuples)
nameList=list(zip(names,assignments))

### Extract models closest to cluster centroids
counter=0
while counter&lt;num_Clusters+1:

    # Create mask from the list of assignments for extracting submatrix of the cluster
    mask=np.array([1 if i==counter else 0 for i in assignments],dtype=bool)

    # Take the index of the column with the smallest sum of distances from the submatrix
    idx=np.argmin(sum(sq[:,mask][mask,:]))

    # Extract names of cluster elements from nameList
    sublist=[name for (name, cluster) in nameList if cluster==counter]

    # Element closest to centroid
    centroid=sublist[idx]
</code></pre>

python numpy scipy scikit-learn