본문 바로가기

Computer Science/Machine Learning

Dendrograms and Heat Plots

데이터 셋은 수업시간에 제공된 자료를 활용했습니다. 데이터의 의미보다는 코딩을 중점으로 봐주세요.

 

# import libraries

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage
from pylab import figure, colorbar

# data upload

data = pd.read_excel("panda_example.xlsx")
enzymes = ["DhlA", "LinB", "DbjA", "DmbA", "DrbA"]
substrates = data["Name"]
halides = data["Halide"]
activity_data = data[enzymes].to_numpy()

 

라이브러리와 데이터를 불러옵니다. 효소와 기질 간의 반응성 정도에 대한 수치 데이터인데, 각각 변수에 저장합니다.

 

Create Multiple Axes

히트맵과 dendrogram을 한 그래프 안에 그리기 위해 자리 배치를 합니다.

 

#create axes

fig = figure(figsize=(10,10))
ax1 = fig.add_axes([0.1, 0.1, 0.2, 0.5])  #left여백, bottom여백, height, width
ax2 = fig.add_axes([0.6, 0.65, 0.3, 0.1])
axm = fig.add_axes([0.6, 0.1, 0.3, 0.5])   #for the hitmap
axcolor = fig.add_axes([0.91, 0.1, 0.02, 0.5])  #color bar

 

다음과 같은 경계선이 그려집니다. 숫자를 조정해보면서 결과를 확인해보세요.

결과적으로 네 부분을 그렸는데, dendrogram을 왼쪽과 맨 위에, 오른쪽 하단은 heat map을, 그리고 컬러바도 추가할 것입니다.

 

Dendrogram

 

#dendrogram

#frist_by substrates
Y = linkage(activity_data)
Z1 = dendrogram(Y, orientation='left', ax=ax1)
idx1 = Z1['leaves']

#second_by enzymes
Y = linkage(activity_data.transpose())
Z2 = dendrogram(Y, ax=ax2)
idx2 = Z2['leaves']

 

orientation = 'left' : vertical dendrogram으로 바꿀 수 있는 인자입니다.

idx1, 2 = dendrogram에서 leave로 출력되는 부분을 저장합니다. 여기에는 dendrogram의 점들 순서대로 저장됩니다.

.transpose() : 데이터 셋에서 행과 열을 뒤집어주는 함수입니다. 

 

Heat Map

 

#heat map

D = activity_data.copy()
D = D[idx1,:]
D = D[:,idx2]
im = axm.matshow(D, aspect='auto', origin='lower')

 

.copy() : 원본 데이터를 손상하지 않고 사용하기 위해 다른 변수에 복사본을 저장합니다.

그리고 leaves 순서대로 reshuffle합니다.

 즉 D=D[idx,:]는 D행렬에서 행의 순서를 leaves대로, 다음줄은 열의 순서를 leaves대로 바꾸는 작업입니다.

그리고나서 matshow라는 함수로 히트맵을 그립니다. D만 인자로 넣고 그려도 되지만 그래프의 비율을 조정할 수 있습니다. aspect에 auto를 넣으면 그린 축 안에 자동으로 맞춰져들어갑니다. origin 인자를 lower로 지정하는 이유는 출력해보시면 알겠지만 왼쪽에 위치시킨 dendrogram과 축순서를 같게 하기 위함입니다. 없어도 상관없습니다.

 

Color Bar, 축 이름

 

# fixing the texts on the axes
ax1.set_xticks([])
ax1.set_yticklabels(substrates[idx1])

ax2.set_xticklabels([enzymes[i] for i in idx2])
ax2.set_yticks([])

axm.set_xticks([])
axm.set_yticks(np.arange(len(idx1)))
axm.set_yticklabels(halides[idx1])

#color bar

colorbar(im, cax=axcolor)
fig.show()

 

첫번쨰줄 : x축 숫자를 비우고 싶어서 빈 리스트를 넣습니다

idx1과 2에 든 순서대로 이름을 넣고 싶어서 위와 같이 작성합니다.

*yticks 함수가 range 함수로 입력이 안돼서 np를 사용했습니다

 

결과는 아래와 같습니다.

 

 

 

더 나아가서, 각 열 별로 정규화하는 법에 대해 고민해보았는데요.

 

activity_data_n = data[enzymes].to_numpy()

## normalize
for i in range(0,27):   
    for j in range(0,5):   
        activity_data_n[i,j] = activity_data[i,j]/activity_data.sum(axis=0)[j]

 

결과가 살짝 다르게 나옵니다.