解释 SciPy 的层次聚类树状图的输出? (也许发现了一个错误...)
Interpreting the output of SciPy's hierarchical clustering dendrogram? (maybe found a bug...)
我想弄清楚 scipy.cluster.hierarchy.dendrogram
的输出是如何工作的...我以为我知道它是如何工作的并且我能够使用输出来重建树状图,但似乎我是不再理解它或者此模块的 Python 3
版本中存在错误。
这个答案,how do I get the subtrees of dendrogram made by scipy.cluster.hierarchy,意味着 dendrogram
输出字典给出 dict_keys(['icoord', 'ivl', 'color_list', 'leaves', 'dcoord'])
w/ 所有大小相同,所以你可以 zip
它们和 plt.plot
他们重建树状图。
看起来很简单,当我使用 Python 2.7.11
时,它确实恢复了工作,但是一旦我升级到 Python 3.5.1
,我的旧脚本就不会给我相同的结果。
我开始为一个非常简单的可重复示例重新设计我的集群,并且认为我可能在 Python 3.5.1 版本的 SciPy version 0.17.1-np110py35_1
中发现了一个错误。要使用 Scikit-learn
数据集 b/c 大多数人都从 conda 发行版中获得该模块。
为什么这些没有排成一行,为什么我无法以这种方式重建树状图?
# Init
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
# Load data
from sklearn.datasets import load_diabetes
# Clustering
from scipy.cluster.hierarchy import dendrogram, fcluster, leaves_list
from scipy.spatial import distance
from fastcluster import linkage # You can use SciPy one too
%matplotlib inline
# Dataset
A_data = load_diabetes().data
DF_diabetes = pd.DataFrame(A_data, columns = ["attr_%d" % j for j in range(A_data.shape[1])])
# Absolute value of correlation matrix, then subtract from 1 for disimilarity
DF_dism = 1 - np.abs(DF_diabetes.corr())
# Compute average linkage
A_dist = distance.squareform(DF_dism.as_matrix())
Z = linkage(A_dist,method="average")
# I modded the SO code from the above answer for the plot function
def plot_tree( D_dendro, ax ):
# Set up plotting data
leaves = D_dendro["ivl"]
icoord = np.array( D_dendro['icoord'] )
dcoord = np.array( D_dendro['dcoord'] )
color_list = D_dendro["color_list"]
# Plot colors
for leaf, xs, ys, color in zip(leaves, icoord, dcoord, color_list):
print(leaf, xs, ys, color, sep="\t")
plt.plot(xs, ys, color)
# Set min/max of plots
xmin, xmax = icoord.min(), icoord.max()
ymin, ymax = dcoord.min(), dcoord.max()
plt.xlim( xmin-10, xmax + 0.1*abs(xmax) )
plt.ylim( ymin, ymax + 0.1*abs(ymax) )
# Set up ticks
ax.set_xticks( np.arange(5, len(leaves) * 10 + 5, 10))
ax.set_xticklabels(leaves, fontsize=10, rotation=45)
plt.show()
fig, ax = plt.subplots()
D1 = dendrogram(Z=Z, labels=DF_dism.index, color_threshold=None, no_plot=True)
plot_tree(D_dendro=D1, ax=ax)
attr_1 [ 15. 15. 25. 25.] [ 0. 0.10333704 0.10333704 0. ] g
attr_4 [ 55. 55. 65. 65.] [ 0. 0.26150727 0.26150727 0. ] r
attr_5 [ 45. 45. 60. 60.] [ 0. 0.4917828 0.4917828 0.26150727] r
attr_2 [ 35. 35. 52.5 52.5] [ 0. 0.59107459 0.59107459 0.4917828 ] b
attr_8 [ 20. 20. 43.75 43.75] [ 0.10333704 0.65064998 0.65064998 0.59107459] b
attr_6 [ 85. 85. 95. 95.] [ 0. 0.60957062 0.60957062 0. ] b
attr_7 [ 75. 75. 90. 90.] [ 0. 0.68142114 0.68142114 0.60957062] b
attr_0 [ 31.875 31.875 82.5 82.5 ] [ 0.65064998 0.72066112 0.72066112 0.68142114] b
attr_3 [ 5. 5. 57.1875 57.1875] [ 0. 0.80554653 0.80554653 0.72066112] b
这是一个 w/o 标签和 x 轴的 icoord
值
所以请检查颜色是否映射正确。它说 icoord
的 [ 15. 15. 25. 25.]
与 attr_1
一致,但基于它看起来与 attr_4
一致的值。此外,它不会一直走到最后一片叶子 (attr_9
),那是 b/c icoord
和 dcoord
的长度比ivl
个标签。
print([len(x) for x in [leaves, icoord, dcoord, color_list]])
#[10, 9, 9, 9]
icoord
、dcoord
和 color_list
描述的是 links,而不是叶子。 icoord
和 dcoord
给出图中每个 link 的 "arches" (即倒置的 U 或 J 形状)的坐标,而 color_list
是那些拱门的颜色。在完整图中,icoord
等的长度将比 ivl
的长度少一个,正如您所观察到的。
不要尝试将 ivl
列表与 icoord
、dcoord
和 color_list
列表对齐。它们与不同的事物相关联。
我想弄清楚 scipy.cluster.hierarchy.dendrogram
的输出是如何工作的...我以为我知道它是如何工作的并且我能够使用输出来重建树状图,但似乎我是不再理解它或者此模块的 Python 3
版本中存在错误。
这个答案,how do I get the subtrees of dendrogram made by scipy.cluster.hierarchy,意味着 dendrogram
输出字典给出 dict_keys(['icoord', 'ivl', 'color_list', 'leaves', 'dcoord'])
w/ 所有大小相同,所以你可以 zip
它们和 plt.plot
他们重建树状图。
看起来很简单,当我使用 Python 2.7.11
时,它确实恢复了工作,但是一旦我升级到 Python 3.5.1
,我的旧脚本就不会给我相同的结果。
我开始为一个非常简单的可重复示例重新设计我的集群,并且认为我可能在 Python 3.5.1 版本的 SciPy version 0.17.1-np110py35_1
中发现了一个错误。要使用 Scikit-learn
数据集 b/c 大多数人都从 conda 发行版中获得该模块。
为什么这些没有排成一行,为什么我无法以这种方式重建树状图?
# Init
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
# Load data
from sklearn.datasets import load_diabetes
# Clustering
from scipy.cluster.hierarchy import dendrogram, fcluster, leaves_list
from scipy.spatial import distance
from fastcluster import linkage # You can use SciPy one too
%matplotlib inline
# Dataset
A_data = load_diabetes().data
DF_diabetes = pd.DataFrame(A_data, columns = ["attr_%d" % j for j in range(A_data.shape[1])])
# Absolute value of correlation matrix, then subtract from 1 for disimilarity
DF_dism = 1 - np.abs(DF_diabetes.corr())
# Compute average linkage
A_dist = distance.squareform(DF_dism.as_matrix())
Z = linkage(A_dist,method="average")
# I modded the SO code from the above answer for the plot function
def plot_tree( D_dendro, ax ):
# Set up plotting data
leaves = D_dendro["ivl"]
icoord = np.array( D_dendro['icoord'] )
dcoord = np.array( D_dendro['dcoord'] )
color_list = D_dendro["color_list"]
# Plot colors
for leaf, xs, ys, color in zip(leaves, icoord, dcoord, color_list):
print(leaf, xs, ys, color, sep="\t")
plt.plot(xs, ys, color)
# Set min/max of plots
xmin, xmax = icoord.min(), icoord.max()
ymin, ymax = dcoord.min(), dcoord.max()
plt.xlim( xmin-10, xmax + 0.1*abs(xmax) )
plt.ylim( ymin, ymax + 0.1*abs(ymax) )
# Set up ticks
ax.set_xticks( np.arange(5, len(leaves) * 10 + 5, 10))
ax.set_xticklabels(leaves, fontsize=10, rotation=45)
plt.show()
fig, ax = plt.subplots()
D1 = dendrogram(Z=Z, labels=DF_dism.index, color_threshold=None, no_plot=True)
plot_tree(D_dendro=D1, ax=ax)
attr_1 [ 15. 15. 25. 25.] [ 0. 0.10333704 0.10333704 0. ] g
attr_4 [ 55. 55. 65. 65.] [ 0. 0.26150727 0.26150727 0. ] r
attr_5 [ 45. 45. 60. 60.] [ 0. 0.4917828 0.4917828 0.26150727] r
attr_2 [ 35. 35. 52.5 52.5] [ 0. 0.59107459 0.59107459 0.4917828 ] b
attr_8 [ 20. 20. 43.75 43.75] [ 0.10333704 0.65064998 0.65064998 0.59107459] b
attr_6 [ 85. 85. 95. 95.] [ 0. 0.60957062 0.60957062 0. ] b
attr_7 [ 75. 75. 90. 90.] [ 0. 0.68142114 0.68142114 0.60957062] b
attr_0 [ 31.875 31.875 82.5 82.5 ] [ 0.65064998 0.72066112 0.72066112 0.68142114] b
attr_3 [ 5. 5. 57.1875 57.1875] [ 0. 0.80554653 0.80554653 0.72066112] b
这是一个 w/o 标签和 x 轴的 icoord
值
所以请检查颜色是否映射正确。它说 icoord
的 [ 15. 15. 25. 25.]
与 attr_1
一致,但基于它看起来与 attr_4
一致的值。此外,它不会一直走到最后一片叶子 (attr_9
),那是 b/c icoord
和 dcoord
的长度比ivl
个标签。
print([len(x) for x in [leaves, icoord, dcoord, color_list]])
#[10, 9, 9, 9]
icoord
、dcoord
和 color_list
描述的是 links,而不是叶子。 icoord
和 dcoord
给出图中每个 link 的 "arches" (即倒置的 U 或 J 形状)的坐标,而 color_list
是那些拱门的颜色。在完整图中,icoord
等的长度将比 ivl
的长度少一个,正如您所观察到的。
不要尝试将 ivl
列表与 icoord
、dcoord
和 color_list
列表对齐。它们与不同的事物相关联。