Метрика, которая использовалась для linkage()
, представляет собой евклидово расстояние, см. здесь , а не фактические значения.Следовательно, оно может превышать 2, и оно зависит только от типа метрики расстояния, которое мы используем.
Это поддерживает точки, упомянутые в этом ответе.
1) Ось Y является мерой близости отдельных точек данных или кластеров.
Затем эти расстояния используются для вычисления дерева с использованием следующего вычисления между каждой парой кластеров.
Из документации:
В упомянутом образце
Даже если отдельные значения не выходят за пределы (-1, +1)
, мы получим следующую дендрограмму.
from scipy.spatial import distance
distance.pdist(df, 'euclidean')
Причина в том, что массив расстояний размером 45 (10 C 2
- каждая пара столбцов;порядок объясняется здесь ) будет иметь следующие значения:
array([1.546726 , 0.79914141, 0.79426728, 2.24085106, 2.50838998,
2.22772899, 2.52578923, 2.55978527, 2.51553289, 2.11329023,
2.10501739, 1.66536963, 1.6303103 , 1.71821177, 2.04386712,
2.03917033, 2.03614219, 0.0280283 , 2.33440388, 2.68373496,
2.43771817, 2.68351612, 2.73148741, 2.66843754, 2.31758222,
2.67031469, 2.4206485 , 2.66539997, 2.7134241 , 2.65058045,
1.44756593, 1.39699605, 1.55063416, 1.56324546, 1.52001219,
1.32204039, 1.30206957, 1.29596715, 1.2895916 , 0.65145881,
0.62242858, 0.6283212 , 0.08642582, 0.11145739, 0.14420816])
Если мы построим матрицу случайных значений с равномерным dist.(-1, 1)
размером (160, 160)
, дендрограмма будет выглядеть примерно так!
Следовательно, решение вашей проблемы:
Вам необходимо преобразовать значения корреляции в некоторую форму меры расстояния.
мы могли бы использовать ту же квадратную форму () , предложенную в другом ответе .Это метод клейкой ленты для достижения двух аспектов измерения расстояния.Он должен быть нулевым [между одними и теми же двумя точками] и неотрицательным для любых двух точек.Это может быть достигнуто путем вычитания каждого значения corr из одного.
Непосредственно мы можем использовать функцию distance.pdist
с корреляцией в качестве метрики.Реализация доступна здесь .Не забудьте преобразовать фрейм данных, потому что нам нужна корреляция между каждым столбцом, а не строкой.
Пример для понимания решения:
size = (10000,1)
col1 = np.random.randint(0,100,size) # base column
col2 = col1 * 0.9 + np.random.normal(0,2,size) # huge corr with small noise
col3 = col1 * 0.1 + np.random.normal(0,100,size) # uncorrelated column
col4 = col1 * (-0.5) + np.random.normal(0,1,size) # negatively corr
data = np.hstack((col1,col2,col3,col4))
df = pd.DataFrame(data , columns=list('ABCD'))
df.corr()
A B C D
A 1.000000 0.997042 0.029078 -0.997614
B 0.997042 1.000000 0.029233 -0.994677
C 0.029078 0.029233 1.000000 -0.028421
D -0.997614 -0.994677 -0.028421 1.000000
#pdist_values = distance.squareform(1 - df.corr().values )
pdist_values = distance.pdist(df.T, 'correlation')
z = linkage(pdist_values, method='average')
dendrogram(z, labels=df.columns)