匹配scipy链接()和树状图()的输出

92dk7w1h  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(134)

我使用如下代码的ZP输出从头开始绘制树状图(请参见下面的完整示例):

Z = scipy.cluster.hierarchy.linkage(...)
P = scipy.cluster.hierarchy.dendrogram(Z, ..., no_plot=True)

为了完成我想做的事情,我需要匹配P["icoord"]/P["dcoord"]中的一个给定索引(其中包含在图中绘制聚类连锁的坐标)与Z中的相应索引(其中包含关于哪些数据元素在哪个聚类中的信息),或者反之亦然。P["icoord"]/P["dcoord"]中簇的位置正好与Z中的相应位置匹配(请参见下面代码的输出以获得证明)。

**问题:我需要一个函数Z_i = f(P_coords_i)或它的反函数P_coords_i = g(Z_i),这样我就可以迭代一个列表,并轻松地访问另一个列表中的相应元素。

下面的代码生成了26个随机点,并用字母表中的字母标记它们,然后打印出与Z的行所表示的聚类相对应的字母,然后打印出Pdcoord为零的点(即叶节点),以证明它们通常不匹配:例如,Z的第一个元素对应于群集iu,但是P["icoord"]/P["dcoord"]中的第一组点对应于绘制jy的群集,而iu的第一组点直到几个元素之后才出现。

import numpy as np
from scipy.cluster import hierarchy
from scipy.spatial import distance
import string

# let's make some random data

np.random.seed(1)
data = np.random.multivariate_normal([0,0],[[5, 0], [0, 1]], 26)
letters = list(string.ascii_lowercase)
X = distance.pdist(data)

# here's the code I need to run for my use-case

Z = hierarchy.linkage(X)
P = hierarchy.dendrogram(Z, labels=letters, no_plot=True)

# let's look at the order of Z

print("Z:")

clusters = letters.copy()

for c1, c2, _, _ in Z:
    clusters.append(clusters[int(c1)]+clusters[int(c2)])
    print(clusters[-1])

# now let's look at the order of P["icoord"] and P["dcoord"]

print("\nP:")

def lookup(y, x):
    return "?" if y else P["ivl"][int((x-5)/10)]

for ((x1,x2,x3,x4),(y1,y2,y3,y4)) in zip(P["icoord"], P["dcoord"]):
     print(lookup(y1, x1)+lookup(y4, x4))

输出量:

------Z:
iu
ez
niu
jy
ad
pr
bq
prbq
wniu
gwniu
ezgwniu
hm
ojy
prbqezgwniu
ks
ojyprbqezgwniu
vks
ojyprbqezgwniuvks
lhm
adlhm
fadlhm
cfadlhm
tcfadlhm
ojyprbqezgwniuvkstcfadlhm
xojyprbqezgwniuvkstcfadlhm

------P:
jy
o?
pr
bq
??
ez
iu
n?
w?
g?
??
??
??
ks
v?
??
ad
hm
l?
??
f?
c?
t?
??
x?
zsohkypk

zsohkypk1#

**关键思想:**模仿构造R['icoord']/R['dcoord']的代码。将簇idx附加到一个空列表cluster_id_list中,附加的方式是链接信息被附加。cluster_id_listR['icoord']/R['dcoord']中的元素将被“对齐”。

您可以考虑以下代码:

def append_index(n, i, cluster_id_list):
    # refer to the recursive progress in
    # https://github.com/scipy/scipy/blob/4cf21e753cf937d1c6c2d2a0e372fbc1dbbeea81/scipy/cluster/hierarchy.py#L3549

    # i is the idx of cluster(counting in all 2 * n - 1 clusters)
    # so i-n is the idx in the "Z"
    if i < n:
        return
    aa = int(Z[i - n, 0])
    ab = int(Z[i - n, 1])

    append_index(n, aa, cluster_id_list)
    append_index(n, ab, cluster_id_list)

    cluster_id_list.append(i-n)
    # Imitate the progress in hierarchy.dendrogram
    # so how `i-n` is appended , is the same as how the element in 'icoord'&'dcoord' be.
    return

def get_linkid_clusterid_relation(Z):
    Zs = Z.shape
    n = Zs[0] + 1
    i = 2 * n - 2
    cluster_id_list = []
    append_index(n, i, cluster_id_list)
    # cluster_id_list[i] is the cluster idx(in Z) that the R['icoord'][i]/R['dcoord'][i] corresponds to

    dict_linkid_2_clusterid = {linkid: clusterid for linkid, clusterid in enumerate(cluster_id_list)}
    dict_clusterid_2_linkid = {clusterid: linkid for linkid, clusterid in enumerate(cluster_id_list)}
    return dict_linkid_2_clusterid, dict_clusterid_2_linkid

我只是模仿了dendrogram函数调用_dendrogram_calculate_info函数的递归过程。dict_linkid_2_clusterid给出了每个链接属于哪个簇。dict_linkid_2_clusterid[i]P["icoord"][i]/P["dcoord"][i]对应的簇,即Z数组中idx的索引。dict_clusterid_2_linkid是逆Map。

**注意:**如果使用count_sortdistance_sort,这将影响添加链接的顺序。您可以通过添加额外的代码从scipy源代码扩展我的答案。参数truncate_mode也可以考虑在内。

测试代码:

dict_linkid_2_clusterid, dict_clusterid_2_linkid = get_linkid_clusterid_relation(Z)
for linkid, _ in enumerate(zip(P["icoord"], P["dcoord"])):
    clusterid = dict_linkid_2_clusterid[linkid]
    c1, c2, _, _ = Z[clusterid]
    print(clusters[int(c1)] + clusters[int(c2)])

您可以看到,您可以在原始代码中填充未知的y

4xrmg8kj

4xrmg8kj2#

首先,定义叶标签函数。

def llf(id):
    if id < n:
        return str(id)
    else:
        return '[%d %d %1.2f]' % (id, count, R[n-id,3])

相关问题