带图的树状图-如何设置层次聚类的自定义链接方法

问题描述

我对Plot还不熟悉,需要绘制具有组平均链接的树形图。

我知道distfun中有一个distfun参数,但我不知道要向该参数传递什么才能获得Group Average Linkage。distfun参数显然必须是可调用的。我应该向它传递什么函数?

作为附注,我有一个成对距离矩阵示例 0 13 0 2 14 0 17 1 18 0 当我传递给create_dendrogram()方法时,它似乎产生了不正确的结果。我在这里做错了什么?

编码:

import plotly.figure_factory as ff

import numpy as np

X = np.matrix([[0,0,0,0],[13,0,0,0],[2,14,0,0],[17,1,18,0]])

names = list("0123")
fig = ff.create_dendrogram(X, orientation='left', labels=names)
fig.update_layout(width=800, height=800)
fig.show()

代码直接从我应该做的BC idk网站复制而来。 此网站:https://plotly.com/python/v3/dendrogram/


解决方案

这有点老了,但是,对于任何有类似问题的其他人,我认为distfun参数只是指定您希望如何将数据矩阵转换为压缩距离矩阵-您可以自己定义函数。

例如,在稍微撞了一下头之后,我拼凑在一起将数据矩阵转换为Jaccard距离矩阵,然后将其压缩。您应该知道,Plot的树状图实现不会检查您的矩阵是否压缩,因此您的distfun需要确保发生这种情况。这可能是错误的,但看起来distfun应该只接受一个位置参数(数据矩阵)并返回一个对象(压缩距离矩阵):

import plotly.figure_factory as ff
import numpy as np
from scipy.spatial.distance import jaccard, squareform

def jaccard_dissimilarity(feature_list1, feature_list2, filler_val): #binary
    all_features = set([i for i in feature_list1 if i != filler_val])#filler val can be used to even up ragged lists and ignore certain dtypes ie prots not in a module
    all_features.update(set([i for i in feature_list2 if i != filler_val]))#works for both numpy arrays and lists
    counts_1 = [1 if feature in feature_list1 else 0 for feature in all_features]
    counts_2 = [1 if feature in feature_list2 else 0 for feature in all_features]
    return jaccard(counts_1, counts_2)

def data_to_dist_matrix(mn_data, filler_val = 0):
    #notes:
        #the original plotly example uses pdist to find manhatten distance for clustering.  
        #pdist 'Returns a condensed distance matrix Y' - https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.pdist.html#scipy.spatial.distance.pdist.
        #a condensed distance matrix is required for input into scipy linkage for clustering.  
        #plotly dendrogram function does not do this conversion to the output of a given distfun call - https://github.com/plotly/plotly.py/blob/cfad7862594b35965c0e000813bd7805e8494a5b/packages/python/plotly/plotly/figure_factory/_dendrogram.py#L340
        #therefore you should convert distance matrix to condensed form yourself as below with squareform
    distance_matrix = np.array([[jaccard_dissimilarity(a,b, filler_val) for b in mn_data] for a in mn_data])
    return squareform(distance_matrix)



# toy data to visually check clustering looks sensible
data_array = np.array([[1, 2, 3,0], 
                       [2, 3, 10, 0], 
                       [4, 5, 6, 0],
                       [5, 6, 7, 0],
                       [7, 8, 1, 0],
                       [1,2,8,7],
                       [1,2,3,8],
                       [1,2,3,4]])

y_labels = [f'MODULE_{i}' for i in range(8)]

#this is the distance matrix and condensed distance matrix made by data_to_dist_matrix and is only included so I can check what it's doing
dist_matrix = np.array([[jaccard_dissimilarity(a,b, 0) for b in data_array] for a in data_array])
condensed_dist_matrix = data_to_dist_matrix(data_array, 0)

# Create Side Dendrogram
fig = ff.create_dendrogram(data_array, 
                           orientation='right', 
                           labels = y_labels,
                           distfun = data_to_dist_matrix)

相关文章