Dans R, vous pouvez dessiner une carte thermique avec un dendrogramme regroupé pour chaque axe de x et y en tapant simplement heat map (x)
, et le niveau d'expression des gènes est familier aux bioinformaticiens qui marmonnent tous les jours. C'est une fonction de, mais quand j'ai essayé de faire la même chose dans l'environnement Python + matplotlib, il n'y avait pas beaucoup d'informations, donc je l'ai essayé par essais et erreurs.
Je le publierai sous forme de mémorandum.
Tout d'abord, en tant que données appropriées, créez des données qui montrent l'augmentation ou la diminution du niveau d'expression génique pour chaque tissu cellulaire.
Les choix de tissus et de gènes ici sont tous appropriés.
Nous allons modifier les données générées aléatoirement en un objet pandas.DataFrame
afin qu'il lui ressemble une fois mis en cluster plus tard.
python
#!/usr/bin/env python3
genes = [
'HIST1H4H', 'SPRN', 'DNLZ', 'PYCARD', 'PRDM11', 'DKKL1', 'CYBRD1', 'DMAP1',
'MT1E', 'PDGFRL', 'SERTM1', 'PIFO', 'FAM109A', 'ST5', 'ABCA7', 'FAM160A1',
'SAMD15', 'NUAK1', 'GLTP', 'HIST3H2A', 'SCN5A', 'PNPLA5', 'SFRP5', 'CCBE1',
'PTCD1', 'RFTN1', 'SYTL2', 'FAM65B', 'NFKBIZ', 'RHOG', 'KIF3A', 'DYRK1B',
'NXPH2', 'APLN', 'ZNF526', 'NRIP3', 'KCNMA1', 'MTSS1', 'ZNF566', 'TNC',
'GPX2', 'AQP3', 'TSACC', 'SNX15', 'TRIM22', 'THAP6', 'GRIP1', 'DLGAP3',
]
tissues = [
'brain', 'kidney', 'lung', 'heart',
'liver', 'pancreas', 'testis', 'placenta',
]
def draw_heatmap(a):
print(a.head())
def _main():
from random import choice
import numpy as np
from pandas import DataFrame
v = np.random.random([4, len(tissues)]) * 1.2 - 0.6
w = np.random.random([3, len(genes)]) * 0.8 - 0.4
v = np.vstack([choice(v) for x in genes])
w = np.vstack([choice(w) for x in tissues]).T
a = DataFrame(v + w, index=genes, columns=tissues)
draw_heatmap(a)
if __name__ == '__main__':
_main()
Résultat d'exécution
brain kidney lung heart liver pancreas \
HIST1H4H -0.085630 0.074054 0.058026 -0.142751 -0.767515 -0.348885
SPRN -0.424203 0.251821 -0.012052 -0.037645 -0.000477 0.714727
DNLZ 0.372402 0.532086 0.097971 -0.102806 -0.727570 0.109148
PYCARD -0.561378 0.114647 0.706732 0.681139 0.718306 0.577552
PRDM11 -0.698969 -0.022945 0.240133 0.214540 0.251708 0.439960
testis placenta
HIST1H4H 0.324709 -0.319531
SPRN -0.815679 -0.010529
DNLZ 0.402956 -0.241284
PYCARD -0.728135 0.077015
PRDM11 -0.773637 0.031513
A partir de maintenant, nous ne jouerons qu'avec la fonction draw_heatmap (a)
.
Si vous voulez vérifier uniquement les données pour le moment, au lieu de créer des matériaux, vous pouvez les afficher en insérant les données dans ʻimshow () de
matplotlib` comme suit.
def draw_heatmap(a):
from matplotlib import pyplot as plt
plt.imshow(a, aspect='auto', interpolation='none')
plt.colorbar()
plt.xticks(range(a.shape[1]), a.columns)
plt.yticks(range(a.shape[0]), a.index)
plt.show()
Nous allons le faire paraître un peu mieux que l'exemple ci-dessus.
from matplotlib.colors import LinearSegmentedColormap
microarray_cmap = LinearSegmentedColormap('microarray', {
'red': [(0.0, 1.0, 1.0), (0.5, 0.2, 0.2), (1.0, 0.0, 0.0)],
'green': [(0.0, 0.0, 0.0), (0.5, 0.2, 0.2), (1.0, 1.0, 1.0)],
'blue': [(0.0, 0.0, 0.0), (0.5, 0.2, 0.2), (1.0, 0.0, 0.0)],
})
def draw_heatmap(a, cmap=microarray_cmap):
from matplotlib import pyplot as plt
plt.imshow(a, aspect='auto', interpolation='none',
cmap=cmap, vmin=-1.0, vmax=1.0)
plt.colorbar()
plt.xticks(range(a.shape[1]), a.columns, rotation=15)
plt.yticks(range(a.shape[0]), a.index, size='small')
plt.gca().get_xaxis().set_ticks_position('none')
plt.gca().get_yaxis().set_ticks_position('none')
plt.show()
La palette de couleurs qui passe du rouge au noir au vert n'est pas dans le préréglage de matplotlib, donc je la définis moi-même avec LinearSegmentedColormap
.
Si 0 est complètement noir, la différence proche de 0 est trop faible en luminosité pour être comprise, alors j'ose faire le gris foncé moyen.
Il est plus facile de voir en regroupant des gènes avec des modèles d'expression similaires.
def draw_heatmap(a, cmap=microarray_cmap):
from matplotlib import pyplot as plt
from scipy.spatial.distance import pdist
from scipy.cluster.hierarchy import linkage, dendrogram
metric = 'euclidean'
method = 'average'
plt.subplot(1, 2, 1)
ylinkage =linkage(pdist(a, metric=metric), method=method, metric=metric)
ydendro = dendrogram(ylinkage, orientation='right', no_labels=True,
distance_sort='descending')
a = a.ix[[a.index[i] for i in ydendro['leaves']]]
plt.subplot(1, 2, 2)
plt.imshow(a, aspect='auto', interpolation='none',
cmap=cmap, vmin=-1.0, vmax=1.0)
plt.colorbar()
plt.xticks(range(a.shape[1]), a.columns, rotation=15)
plt.yticks(range(a.shape[0]), a.index, size='small')
plt.gca().xaxis.set_ticks_position('none')
plt.gca().yaxis.set_ticks_position('none')
plt.gca().invert_yaxis()
plt.show()
Utilisez la fonction Scipy pour effectuer un regroupement hiérarchique et dessinez côte à côte avec le dendrogramme.
dendrogram (..., no_plot = True)
.a le coin supérieur gauche comme origine, tandis que
dendrogram () a le bas gauche comme origine, alors utilisez ʻinvert_yaxis ()
pour changer la direction de l'axe.Rend l'exemple ci-dessus beau.
def draw_heatmap(a, cmap=microarray_cmap):
from matplotlib import pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from scipy.spatial.distance import pdist
from scipy.cluster.hierarchy import linkage, dendrogram
metric = 'euclidean'
method = 'average'
main_axes = plt.gca()
divider = make_axes_locatable(main_axes)
plt.sca(divider.append_axes("left", 1.0, pad=0))
ylinkage = linkage(pdist(a, metric=metric), method=method, metric=metric)
ydendro = dendrogram(ylinkage, orientation='right', no_labels=True,
distance_sort='descending',
link_color_func=lambda x: 'black')
plt.gca().set_axis_off()
a = a.ix[[a.index[i] for i in ydendro['leaves']]]
plt.sca(main_axes)
plt.imshow(a, aspect='auto', interpolation='none',
cmap=cmap, vmin=-1.0, vmax=1.0)
plt.colorbar(pad=0.15)
plt.gca().yaxis.tick_right()
plt.xticks(range(a.shape[1]), a.columns, rotation=15, size='small')
plt.yticks(range(a.shape[0]), a.index, size='small')
plt.gca().xaxis.set_ticks_position('none')
plt.gca().yaxis.set_ticks_position('none')
plt.gca().invert_yaxis()
plt.show()
make_axes_locatable ()
au lieu de subplot ()
.set_axis_off ()
et la ligne est noire uniquement avec link_color_func
.yaxis.tick_right ()
amène l'étiquette de l'axe y vers la droite. Puisqu'il chevauche la barre de couleur telle quelle, l'intervalle est élargi comme colorbar (pad = ...)
.Ce n'est pas nécessaire pour les données chronologiques, mais il peut être plus facile de comprendre si l'axe des x est également regroupé pour les données de chaque organisation. Ce que vous faites est fondamentalement le même qu'avant.
def draw_heatmap(a, cmap=microarray_cmap):
from matplotlib import pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from scipy.spatial.distance import pdist
from scipy.cluster.hierarchy import linkage, dendrogram
metric = 'euclidean'
method = 'average'
main_axes = plt.gca()
divider = make_axes_locatable(main_axes)
xdendro_axes = divider.append_axes("top", 0.5, pad=0)
ydendro_axes = divider.append_axes("left", 1.0, pad=0)
plt.sca(xdendro_axes)
xlinkage = linkage(pdist(a.T, metric=metric), method=method, metric=metric)
xdendro = dendrogram(xlinkage, orientation='top', no_labels=True,
distance_sort='descending',
link_color_func=lambda x: 'black')
plt.gca().set_axis_off()
a = a[[a.columns[i] for i in xdendro['leaves']]]
plt.sca(ydendro_axes)
ylinkage = linkage(pdist(a, metric=metric), method=method,
metric=metric)
ydendro = dendrogram(ylinkage, orientation='right', no_labels=True,
distance_sort='descending',
link_color_func=lambda x: 'black')
plt.gca().set_axis_off()
a = a.ix[[a.index[i] for i in ydendro['leaves']]]
plt.sca(main_axes)
plt.imshow(a, aspect='auto', interpolation='none',
cmap=cmap, vmin=-1.0, vmax=1.0)
plt.colorbar(pad=0.15)
plt.gca().yaxis.tick_right()
plt.xticks(range(a.shape[1]), a.columns, rotation=15, size='small')
plt.yticks(range(a.shape[0]), a.index, size='x-small')
plt.gca().xaxis.set_ticks_position('none')
plt.gca().yaxis.set_ticks_position('none')
plt.gca().invert_yaxis()
plt.show()
Après cela, collez-le simplement dans le papier avec savefig ('hoge.eps')
et ainsi de suite.
Au fait, j'ai le sentiment que la signification de «dendrogramme (orientation = ...)» est différente entre paysage et portrait ... Scipy bug?
Recommended Posts