123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- from pprint import pprint
- from argparse import ArgumentParser
- from util import getQuery, pickleQuery
- import numpy as np
- import pandas as p
- import matplotlib
- matplotlib.use('agg')
- import matplotlib.pyplot as plt
- import seaborn as sns
- from scipy.spatial.distance import squareform
- from scipy.cluster.hierarchy import dendrogram, linkage, cophenet, fcluster
- from tqdm import tqdm
- from itertools import combinations
- from math import factorial as f
-
-
- def cluster(dcmat, method, nclusters):
- """Cluster provided correlation dataframe
- """
- lmat = squareform(dcmat)
- lobj = linkage(lmat, method = method)
- clabs = [x + 1 for x in range(numclusts)]
- clusts = fcluster(lobj, numclusts, criterion='maxclust')
- clustdf = p.DataFrame({'icp_id' : dcmat.index.values, 'cluster' : clusts})
- return lobj, clustdf
-
-
- def dendro(lobj, clustdf, numclusts, icps, fname):
- clabs = [x + 1 for x in range(numclusts)]
- cpal = dict(zip(clabs, sns.color_palette("colorblind", numclusts).as_hex()))
-
- # Algorithm via
- # <https://stackoverflow.com/questions/38153829/custom-cluster-colors-of-scipy-dendrogram-in-python-link-color-func>
- ldict = {icp_id:cpal[cluster] for icp_id, cluster in zip(clustdf.icp_id, clustdf.cluster)}
- link_cols = {}
- for i, i12 in enumerate(lobj[:,:2].astype(int)):
- c1, c2 = (link_cols[x] if x > len(lobj) else ldict[clustdf.icp_id[x]]
- for x in i12)
- link_cols[i+1+len(lobj)] = c1 if c1 == c2 else '#000000'
-
- plt.figure(figsize = (25, 10))
- plt.title('ICP Clustering Dendrogram')
- plt.xlabel('ICP ID/(Number of ICPs)')
- plt.ylabel('distance')
- dendrogram(
- lobj,
- labels = icps,
- leaf_rotation=90,
- leaf_font_size=8,
- link_color_func = lambda x: link_cols[x],
- color_threshold = None
- )
- plt.savefig(fname)
-
-
- def main():
- parser = ArgumentParser(description='Cluster from pre-existing distance correlation matrix in pickled dataframe')
- parser.add_argument("-i", "--input", dest="input", help = "input pickle path; default: ../data/5kdcorrmatrix.pkl", metavar="[PATH]", default = "../data/5kdcorrmatrix.pkl")
- parser.add_argument("-o", "--output", dest="output", help = "output pickle path; default: ../data/5kdclustable.pkl", metavar="[PATH]", default = "../data/5kdclustable.pkl")
- parser.add_argument("--method", dest="method", help = "clustering method; default 'ward'", metavar = "[METHOD]", default = "ward")
- parser.add_argument("--clusters", dest="numclusters", help = "number of clusters; default: 9", metavar = "[NUM]", default = 9, type = int)
- parser.add_argument("-d", "--dendrogram", dest = "incdendro", help = "draw dendrogram", action ="store_true")
- parser.add_argument("-t", "--tree", dest="treepath", help="Filename for dendrogram (if -d), default: ../img/59-9-dendro.png", metavar="[PATH]", default = "../img/5k-9-dendro.png")
- args = parser.parse_args()
-
- print("Clustering")
- sourcep = p.read_pickle(args.input)
- l, c = cluster(sourcep, args.method, args.numclusters)
- c.to_pickle(args.output)
-
- print("Drawing dendrogram")
- if args.incdendro:
- icps = sourcep.index.values
- dendro(l, c, args.numclusters, icps, args.treepath)
-
-
- if __name__ == "__main__":
- main()
|