根据相似性度量(例如余弦相似性等)对 Holoviews 热图的列和行进行重新排序
Reorder columns and rows of Holoviews Heatmap based on similarity measure (e.g. cosine similarity etc.)
我很惊讶之前似乎没有人问过这个问题。
假设我有一个 pandas 数据框(随机示例),我可以获得带有 Holoviews 和 Bokeh 渲染器的热图:
rownames = 'ABCDEFGHIJKLMNO'
df = pd.DataFrame(np.random.randint(0,20,size=(20, len(rownames))), columns=list(rownames))
hv.HeatMap({'x': df.columns, 'y': df.index, 'z': df},
kdims=[('x', 'Col Categories'), ('y', 'Row Categories')],
vdims='z').opts(cmap="viridis", width=520, height=520)
数据(x 和 y)是分类数据,因此行或列的初始顺序并不重要。我想根据一些相似性度量对 rows/columns 进行排序。
一种方法是使用seaborn clustermap:
heatmap_sns = sns.clustermap(df, metric="cosine", standard_scale=1, method="ward", cmap="viridis")
输出如下所示:
列和行已根据相似性排序(在本例中,余弦基于点积;其他可用,例如 'correlation' 等)。
但是,我想在 Holoviews 中显示 clustermap。如何从 seaborn 矩阵更新原始数据帧的顺序?
可以使用以下方法从 seaborn clustermap 访问重新排序的 columns/rows 的索引:
> print(f'rows: {heatmap_sns.dendrogram_row.reordered_ind}')
> print(f'columns: {heatmap_sns.dendrogram_col.reordered_ind}')
rows: [5, 0, 13, 2, 18, 7, 4, 16, 12, 19, 14, 15, 10, 3, 8, 6, 17, 11, 1, 9]
columns: [7, 1, 10, 5, 9, 0, 8, 13, 2, 6, 14, 3, 4, 11, 12]
要更新 row/column 原始数据帧的顺序:
# get col and row names by ID
colname_list = [df.columns[col_id] for col_id in heatmap_sns.dendrogram_col.reordered_ind]
rowname_list = [df.index[row_id] for row_id in heatmap_sns.dendrogram_row.reordered_ind]
# update dataframe
df_ro = df.reindex(rowname_list)
df_ro = df_ro[colname_list]
我在这里是通过首先获取名称来完成的,也许甚至还有一种直接的方法可以通过索引更新 columns/rows。
hv.HeatMap({'x': df_ro.columns, 'y': df_ro.index, 'z': df_ro},
kdims=[('x', 'Col Categories'), ('y', 'Row Categories')],
vdims='z').opts(cmap="viridis", width=520, height=520)
由于我使用的是随机数据,因此类别中的顺序很少,但图片看起来还是少了一些噪点。请注意,holoviews/df y 轴与 seaborn clustermap-matrix 相比只是反向的,这就是图形看起来翻转的原因。
Alex 的答案(即之前接受的答案)的一种更简洁的方法是使用 sns.clustermap()
函数返回对象的 data2d
属性。这个 属性 包含重新排序的数据(即聚类后的数据)。所以:
df_ro = heatmap_sns.data2d
替换以下所有行:
# get col and row names by ID
colname_list = [df.columns[col_id] for col_id in
heatmap_sns.dendrogram_col.reordered_ind]
rowname_list = [df.index[row_id] for row_id in
heatmap_sns.dendrogram_row.reordered_ind]
# update dataframe
df_ro = df.reindex(rowname_list)
df_ro = df_ro[colname_list]
我很惊讶之前似乎没有人问过这个问题。
假设我有一个 pandas 数据框(随机示例),我可以获得带有 Holoviews 和 Bokeh 渲染器的热图:
rownames = 'ABCDEFGHIJKLMNO'
df = pd.DataFrame(np.random.randint(0,20,size=(20, len(rownames))), columns=list(rownames))
hv.HeatMap({'x': df.columns, 'y': df.index, 'z': df},
kdims=[('x', 'Col Categories'), ('y', 'Row Categories')],
vdims='z').opts(cmap="viridis", width=520, height=520)
数据(x 和 y)是分类数据,因此行或列的初始顺序并不重要。我想根据一些相似性度量对 rows/columns 进行排序。
一种方法是使用seaborn clustermap:
heatmap_sns = sns.clustermap(df, metric="cosine", standard_scale=1, method="ward", cmap="viridis")
输出如下所示:
列和行已根据相似性排序(在本例中,余弦基于点积;其他可用,例如 'correlation' 等)。
但是,我想在 Holoviews 中显示 clustermap。如何从 seaborn 矩阵更新原始数据帧的顺序?
可以使用以下方法从 seaborn clustermap 访问重新排序的 columns/rows 的索引:
> print(f'rows: {heatmap_sns.dendrogram_row.reordered_ind}')
> print(f'columns: {heatmap_sns.dendrogram_col.reordered_ind}')
rows: [5, 0, 13, 2, 18, 7, 4, 16, 12, 19, 14, 15, 10, 3, 8, 6, 17, 11, 1, 9]
columns: [7, 1, 10, 5, 9, 0, 8, 13, 2, 6, 14, 3, 4, 11, 12]
要更新 row/column 原始数据帧的顺序:
# get col and row names by ID
colname_list = [df.columns[col_id] for col_id in heatmap_sns.dendrogram_col.reordered_ind]
rowname_list = [df.index[row_id] for row_id in heatmap_sns.dendrogram_row.reordered_ind]
# update dataframe
df_ro = df.reindex(rowname_list)
df_ro = df_ro[colname_list]
我在这里是通过首先获取名称来完成的,也许甚至还有一种直接的方法可以通过索引更新 columns/rows。
hv.HeatMap({'x': df_ro.columns, 'y': df_ro.index, 'z': df_ro},
kdims=[('x', 'Col Categories'), ('y', 'Row Categories')],
vdims='z').opts(cmap="viridis", width=520, height=520)
由于我使用的是随机数据,因此类别中的顺序很少,但图片看起来还是少了一些噪点。请注意,holoviews/df y 轴与 seaborn clustermap-matrix 相比只是反向的,这就是图形看起来翻转的原因。
Alex 的答案(即之前接受的答案)的一种更简洁的方法是使用 sns.clustermap()
函数返回对象的 data2d
属性。这个 属性 包含重新排序的数据(即聚类后的数据)。所以:
df_ro = heatmap_sns.data2d
替换以下所有行:
# get col and row names by ID
colname_list = [df.columns[col_id] for col_id in
heatmap_sns.dendrogram_col.reordered_ind]
rowname_list = [df.index[row_id] for row_id in
heatmap_sns.dendrogram_row.reordered_ind]
# update dataframe
df_ro = df.reindex(rowname_list)
df_ro = df_ro[colname_list]