Изменение порядка элементов матрицы для отражения кластеризации столбцов и строк в naiive python

Я ищу способ выполнить кластеризацию отдельно по строкам матрицы, а затем по ее столбцам, переупорядочить данные в матрице, чтобы отразить кластеризацию и собрать все вместе. Проблема кластеризации легко разрешима, как и создание дендрограммы (например, в этот блог или в " Программирование коллективного разума "). Однако мне остается неясным, как изменить порядок данных.

В конце концов, я ищу способ создания графиков, подобных приведенному ниже, с использованием наивного Python (с любой «стандартной» библиотекой, такой как numpy, matplotlib и т. Д., Но без с помощью R или других внешних инструментов).

dendogram
(источник: warwick.ac.uk)

Разъяснения

Меня спросили, что я имел в виду под повторным заказом. Когда вы группируете данные в матрице сначала по строкам матрицы, а затем по ее столбцам, каждая ячейка матрицы может быть идентифицирована по положению в двух дендрограммах. Если вы измените порядок строк и столбцов исходной матрицы таким образом, чтобы элементы, которые находятся рядом друг с другом в дендрограммах, стали ближе друг к другу в матрице, а затем сгенерируете тепловую карту, кластеризация данных может стать очевидной для зрителя. (как на рисунке выше)


person Boris Gorelik    schedule 16.03.2010    source источник
comment
Что вы имеете в виду под переупорядочиванием? Поменять местами n соседних строк / столбцов на другие n?   -  person Hamish Grubijan    schedule 16.03.2010
comment
Вы наверняка хотите использовать numpy / scipy при работе с матрицами. Matplotlib также хорошо имитирует Matlab. Вот сделка: если вы можете сделать это в Matlab, вы можете сделать это и в scipy (тривиальная разница в синтаксисе, если таковая имеется).   -  person Hamish Grubijan    schedule 16.03.2010
comment
Ооо, +1 за красивую картинку ;-)   -  person Beni Cherniavsky-Paskin    schedule 21.03.2010
comment
Я только что разместил это на github: github.com/WarrenWeckesser/heatmapcluster   -  person Warren Weckesser    schedule 31.05.2015


Ответы (3)


См. Мой недавний ответ, частично скопированный ниже, на этот связанный вопрос.

import scipy
import pylab
import scipy.cluster.hierarchy as sch

# Generate features and distance matrix.
x = scipy.rand(40)
D = scipy.zeros([40,40])
for i in range(40):
    for j in range(40):
        D[i,j] = abs(x[i] - x[j])

# Compute and plot dendrogram.
fig = pylab.figure()
axdendro = fig.add_axes([0.09,0.1,0.2,0.8])
Y = sch.linkage(D, method='centroid')
Z = sch.dendrogram(Y, orientation='right')
axdendro.set_xticks([])
axdendro.set_yticks([])

# Plot distance matrix.
axmatrix = fig.add_axes([0.3,0.1,0.6,0.8])
index = Z['leaves']
D = D[index,:]
D = D[:,index]
im = axmatrix.matshow(D, aspect='auto', origin='lower')
axmatrix.set_xticks([])
axmatrix.set_yticks([])

# Plot colorbar.
axcolor = fig.add_axes([0.91,0.1,0.02,0.8])
pylab.colorbar(im, cax=axcolor)

# Display and save figure.
fig.show()
fig.savefig('dendrogram.png')

«Дендрограмма
(источник: stevetjoa.com )

person Steve Tjoa    schedule 10.06.2010

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

>>> x_idxs = [(0,1,0,0),(0,1,1,1),(0,1,1),(0,0,1),(1,1,1,1),(0,0,0,0)]
>>> y_idxs = [(1,1),(0,1),(1,0),(0,0)]
>>> a = np.random.random((len(x_idxs),len(y_idxs)))
>>> x_idxs2, xi = zip(*sorted(zip(x_idxs,range(len(x_idxs)))))
>>> y_idxs2, yi = zip(*sorted(zip(y_idxs,range(len(y_idxs)))))
>>> a2 = a[xi,:][:,yi]

x_idxs и y_idxs - это индикаторы дендрограммы. a - несортированная матрица. xi и yi - это индикаторы вашего нового массива строк / столбцов. a2 - это отсортированная матрица, а x_idxs2 и y_idxs2 - новые отсортированные индикаторы дендрограммы. Это предполагает, что при создании дендрограммы столбец / строка ветвления 0 всегда сравнительно больше / меньше, чем ветвь 1.

Если ваши y_idxs и x_idxs не списки, а массивы numpy, то вы можете использовать np.argsort аналогичным образом.

person Paul    schedule 18.03.2010
comment
что именно * в zip (* отсортировано ... делает? - person Boris Gorelik; 24.03.2010
comment
всякий раз, когда я вижу zip(*, я думаю, что транспонирую. См. Здесь использование * для распаковки: docs.python.org/ руководство / - person Paul; 25.03.2010
comment
и еще несколько обсуждений здесь: stackoverflow.com/ вопросы / 19339 / - person Paul; 25.03.2010

Я знаю, что это очень поздно для игры, но я создал объект для рисования на основе кода из сообщения на этой странице. Он зарегистрирован в pip, поэтому для установки вам просто нужно позвонить

pip install pydendroheatmap

посетите страницу проекта на github здесь: https://github.com/themantalope/pydendroheatmap

person themantalope    schedule 14.07.2015