Как дать sns.clustermap предварительно вычисленную матрицу расстояний?

Обычно, когда я делаю дендрограммы и тепловые карты, я использую матрицу расстояний и делаю кучу вещей SciPy. Я хочу попробовать Seaborn, но Seaborn хочет, чтобы мои данные были в прямоугольной форме (rows = samples, cols = attributes, а не матрица расстояний)?

Я по существу хочу использовать Seaborn в качестве бэкэнд для вычисления моей дендрограммы и привязки ее к моей тепловой карте. Это возможно? Если нет, это может быть особенностью в будущем.

Возможно, есть параметры, которые я могу настроить, поэтому вместо прямоугольной матрицы может взять матрицу расстояний?

Здесь используется:

seaborn.clustermap¶
seaborn.clustermap(data, pivot_kws=None, method='average', metric='euclidean',
 z_score=None, standard_scale=None, figsize=None, cbar_kws=None, row_cluster=True,
 col_cluster=True, row_linkage=None, col_linkage=None, row_colors=None,
 col_colors=None, mask=None, **kwargs)

Мой код ниже:

from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
DF = pd.DataFrame(X, index = ["iris_%d" % (i) for i in range(X.shape[0])], columns = iris.feature_names)

введите описание изображения здесь

Я не думаю, что мой метод является правильным ниже, потому что я даю ему предварительно вычисленную матрицу расстояний и НЕ прямоугольную матрицу данных по ее запросу. Нет примеров использования матрицы корреляции/расстояния с clustermap, но для https://stanford.edu/~mwaskom/software/seaborn/examples/network_correlations.html, но порядок не кластеризован w/простой sns.heatmap func.

DF_corr = DF.T.corr()
DF_dism = 1 - DF_corr
sns.clustermap(DF_dism)

введите описание изображения здесь

Ответ 1

Вы можете передать предварительно вычисленную матрицу расстояний в качестве привязки к clustermap():

import pandas as pd, seaborn as sns
import scipy.spatial as sp, scipy.cluster.hierarchy as hc
from sklearn.datasets import load_iris
sns.set(font="monospace")

iris = load_iris()
X, y = iris.data, iris.target
DF = pd.DataFrame(X, index = ["iris_%d" % (i) for i in range(X.shape[0])], columns = iris.feature_names)

DF_corr = DF.T.corr()
DF_dism = 1 - DF_corr   # distance matrix
linkage = hc.linkage(sp.distance.squareform(DF_dism), method='average')
sns.clustermap(DF_dism, row_linkage=linkage, col_linkage=linkage)

Для clustermap(distance_matrix) (т.е. без передачи связи) связь вычисляется внутренне на основе парных расстояний строк и столбцов в матрице расстояний (см. примечание ниже для полной информации) вместо использования элементов матрицы расстояния напрямую (правильное решение). В результате результат несколько отличается от результата в вопросе: clustermap

Примечание: если row_linkage не передается row_linkage, привязка строки определяется внутренне, рассматривая каждую строку как "точку" (наблюдение) и вычисляя попарные расстояния между точками. Таким образом, дендрограмма строк отражает сходство строк. Аналогично для col_linkage, где каждый столбец считается точкой. Это объяснение должно быть добавлено в docs. Здесь первый пример документов изменен, чтобы сделать внутреннее вычисление ссылок явным:

import seaborn as sns; sns.set()
import scipy.spatial as sp, scipy.cluster.hierarchy as hc
flights = sns.load_dataset("flights")
flights = flights.pivot("month", "year", "passengers")
row_linkage, col_linkage = (hc.linkage(sp.distance.pdist(x), method='average')
  for x in (flights.values, flights.values.T))
g = sns.clustermap(flights, row_linkage=row_linkage, col_linkage=col_linkage) 
  # note: this produces the same plot as "sns.clustermap(flights)", where
  #  clustermap() calculates the row and column linkages internally