Comment créer un dendrogramme en Python avec scipy et matplotlib ?

Published: 25 mars 2014

Updated: 13 septembre 2024

Tags: Matplotlib;

DMCA.com Protection Status

Introduction

Un dendrogramme est un diagramme en forme d'arbre utilisé pour visualiser l'agencement des clusters créés par le regroupement hiérarchique. Il montre comment les points de données individuels (ou les clusters) sont fusionnés étape par étape en fonction de leur similarité ou de leur distance. Les lignes verticales représentent les distances auxquelles les clusters sont combinés, les fusions les plus basses indiquant une plus grande similarité. Les dendrogrammes sont couramment utilisés dans l'analyse de données pour explorer la structure sous-jacente d'un ensemble de données et déterminer le nombre optimal de clusters.

La création d'un dendrogramme en Python peut être effectuée à l'aide de la bibliothèque scipy, qui fournit des outils de regroupement hiérarchique. Voici un guide étape par étape :

Installer les bibliothèques requises

Si vous n'avez pas encore installé scipy et matplotlib, vous pouvez les installer en utilisant :

1
pip install scipy matplotlib

Code de base

Importer les modules nécessaires

Vous devrez importer les fonctions linkage et dendrogram de scipy.cluster.hierarchy, ainsi que matplotlib.pyplot pour les graphiques :

1
2
3
import numpy as np
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage

Préparer vos données

Pour cet exemple, créons un ensemble de données aléatoire :

1
2
3
4
5
6
# Données d'exemple (par exemple, 5 points de données avec 2 caractéristiques chacune)
X = np.array([[1, 2],
              [3, 4],
              [5, 6],
              [7, 8],
              [9, 10]])

Effectuer le regroupement hiérarchique

Utilisez la fonction linkage pour calculer le regroupement hiérarchique. Vous pouvez choisir une méthode telle que ward, single, complete ou average. Voici un exemple avec la méthode ward :

1
2
# Effectuer le regroupement hiérarchique
Z = linkage(X, method='ward')

Tracer le dendrogramme

Enfin, tracez le dendrogramme en utilisant dendrogram :

1
2
3
4
5
6
7
# Tracer le dendrogramme
plt.figure(figsize=(10, 7))
dendrogram(Z)
plt.title("Dendrogramme")
plt.xlabel("Points de données")
plt.ylabel("Distances euclidiennes")
plt.show()

Comment créer un dendrogramme en Python avec scipy et matplotlib ?
Comment créer un dendrogramme en Python avec scipy et matplotlib ?

Un tracé de dendrogramme s'affichera avec le regroupement hiérarchique de votre ensemble de données, montrant comment les points de données sont regroupés à différentes distances.

Code complet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage

# Données d'exemple (par exemple, 5 points de données avec 2 caractéristiques chacune)
X = np.array([[1, 2],
              [3, 4],
              [5, 6],
              [7, 8],
              [9, 10]])

# Effectuer le regroupement hiérarchique
Z = linkage(X, method='ward')

# Tracer le dendrogramme
plt.figure(figsize=(10, 7))
dendrogram(Z)
plt.title("Dendrogramme")
plt.xlabel("Points de données")
plt.ylabel("Distances euclidiennes")
plt.show()

Personnalisation du Dendrogramme

Voici une explication étape par étape du code Python fourni, ainsi que des suggestions pour personnaliser le dendrogramme :

1. Importer les bibliothèques :

1
2
3
from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt
import numpy as np
  • scipy.cluster.hierarchy.dendrogram : Utilisé pour générer le tracé du dendrogramme.
  • scipy.cluster.hierarchy.linkage : Effectue le regroupement hiérarchique.
  • matplotlib.pyplot : Utilisé pour le tracé.
  • numpy : Génère des points de données aléatoires pour le regroupement.

2. Fonction Dendrogramme Personnalisé :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def custom_dendrogram(*args, **kwargs):
    dendro_data = dendrogram(*args, **kwargs)

    if not kwargs.get('no_plot', False):
        for icoord, dcoord in zip(dendro_data['icoord'], dendro_data['dcoord']):
            x_coord = 0.5 * sum(icoord[1:3])  # Point médian du cluster
            height = dcoord[1]  # Distance à laquelle les clusters fusionnent
            plt.plot(x_coord, height, 'ro')  # Tracer un point rouge au point de fusion
            plt.annotate(f"{height:.3g}", (x_coord, height), xytext=(0, -8),
                         textcoords='offset points', va='top', ha='center')  # Annoter la hauteur

    return dendro_data
  • Cette fonction étend le dendrogram par défaut en ajoutant des points rouges et des hauteurs annotées pour chaque point de fusion, améliorant ainsi la lisibilité du dendrogramme.
  • Les annotations montrent les distances exactes auxquelles les clusters fusionnent, fournissant plus de détails sur la structure hiérarchique.

3. Génération de Données Aléatoires :

1
2
3
np.random.seed(12312)
num_points = 100
data = np.random.multivariate_normal([0, 0], np.array([[4.0, 2.5], [2.5, 1.4]]), size=num_points)
  • Génère 100 points 2D aléatoires à partir d'une distribution normale multivariée avec une matrice de moyenne et de covariance spécifiée.
  • Ces données servent d'entrée pour le regroupement hiérarchique.

4. Tracé en Nuage des Données :

1
2
3
4
5
6
7
plt.figure(figsize=(6, 5))
plt.scatter(data[:, 0], data[:, 1])
plt.title("Nuage de points des données")
plt.axis('equal')
plt.grid(True)
plt.savefig('scatter_plot.png')
plt.show()

Comment créer un dendrogramme en Python avec scipy et matplotlib ?
Comment créer un dendrogramme en Python avec scipy et matplotlib ?

Un nuage de points est créé pour visualiser les points de données générés avant d'effectuer le regroupement.

5. Regroupement Hiérarchique :

1
linkage_matrix = linkage(data, method="single")
  • Le regroupement hiérarchique est effectué en utilisant la méthode de liaison simple, qui fusionne les clusters en fonction de la distance minimale entre les points de différents clusters.
  • Le résultat est stocké dans la linkage_matrix, qui est utilisée pour créer les dendrogrammes.

6. Premier Dendrogramme (Sans Comptage des Feuilles) :

1
2
3
4
5
6
7
plt.figure(figsize=(10, 4))
dendro_data = custom_dendrogram(linkage_matrix, color_threshold=1, p=6, truncate_mode='lastp', show_leaf_counts=False)
plt.title("Dendrogramme (Sans Comptage des Feuilles)")
plt.xlabel("Indice de Cluster")
plt.ylabel("Distance")
plt.savefig('dendrogram_without_leaf_counts.png')
plt.show()

Comment créer un dendrogramme en Python avec scipy et matplotlib ?
Comment créer un dendrogramme en Python avec scipy et matplotlib ?

  • Le premier dendrogramme est généré et montre seulement les 6 derniers clusters (truncate_mode='lastp', p=6) sans afficher le comptage des feuilles.

7. Second Dendrogramme (Avec Comptage des Feuilles) :

1
2
3
4
5
6
7
plt.figure(figsize=(10, 4))
dendro_data = custom_dendrogram(linkage_matrix, color_threshold=1, p=6, truncate_mode='lastp', show_leaf_counts=True)
plt.title("Dendrogramme (Avec Comptage des Feuilles)")
plt.xlabel("Indice de Cluster")
plt.ylabel("Distance")
plt.savefig('dendrogram_with_leaf_counts.png')
plt.show()

Comment créer un dendrogramme en Python avec scipy et matplotlib ?
Comment créer un dendrogramme en Python avec scipy et matplotlib ?

  • Ce second dendrogramme inclut les comptes de feuilles, montrant combien de points de données se trouvent dans chaque cluster.

Résumé :

  • Dendrogrammes Personnalisés : La fonction custom_dendrogram améliore le dendrogramme standard en ajoutant des marqueurs visuels et des annotations.
  • Nuage de Points : Affiche les points de données 2D générés aléatoirement.
  • Regroupement Hiérarchique : Utilise la liaison simple pour créer une hiérarchie de regroupement, visualisée dans deux dendrogrammes—l'un sans et l'autre avec le comptage des feuilles.

Code complet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt
import numpy as np

# Custom function for generating a dendrogram with distance annotations
def custom_dendrogram(*args, **kwargs):
    # Create the standard dendrogram
    dendro_data = dendrogram(*args, **kwargs)

    # Add annotations for cluster heights if no_plot is False
    if not kwargs.get('no_plot', False):
        # Loop through the clusters to add custom red dots and distance annotations
        for icoord, dcoord in zip(dendro_data['icoord'], dendro_data['dcoord']):
            x_coord = 0.5 * sum(icoord[1:3])  # Find the midpoint of the cluster
            height = dcoord[1]  # Distance (height) at which the clusters are merged
            plt.plot(x_coord, height, 'ro')  # Plot a red dot at the merge point
            plt.annotate(f"{height:.3g}", (x_coord, height), xytext=(0, -8),
                         textcoords='offset points', va='top', ha='center')  # Annotate the height

    return dendro_data

# Generate random 2D data points for hierarchical clustering
np.random.seed(12312)  # Set seed for reproducibility
num_points = 100  # Number of points
data = np.random.multivariate_normal([0, 0], np.array([[4.0, 2.5], [2.5, 1.4]]), size=num_points)

# Scatter plot of the generated data points
plt.figure(figsize=(6, 5))
plt.scatter(data[:, 0], data[:, 1])
plt.title("Scatter Plot of Data Points")
plt.axis('equal')  # Ensure equal scaling on both axes
plt.grid(True)
plt.savefig('scatter_plot.png')
plt.show()

# Perform hierarchical clustering using the 'single' linkage method
linkage_matrix = linkage(data, method="single")

# Plot the first dendrogram (without leaf counts)
plt.figure(figsize=(10, 4))
dendro_data = custom_dendrogram(linkage_matrix, 
                                color_threshold=1, 
                                p=6, 
                                truncate_mode='lastp', 
                                show_leaf_counts=False)
plt.title("Dendrogram (Without Leaf Counts)")
plt.xlabel("Cluster Index")
plt.ylabel("Distance")
plt.savefig('dendrogram_without_leaf_counts.png')
plt.show()

# Plot the second dendrogram (with leaf counts)
plt.figure(figsize=(10, 4))
dendro_data = custom_dendrogram(linkage_matrix, 
                                color_threshold=1, 
                                p=6, 
                                truncate_mode='lastp', 
                                show_leaf_counts=True)
plt.title("Dendrogram (With Leaf Counts)")
plt.xlabel("Cluster Index")
plt.ylabel("Distance")
plt.savefig('dendrogram_with_leaf_counts.png')
plt.show()

Visualisation du regroupement hiérarchique avec des dendrogrammes superposés sur une matrice de distances

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import numpy as np  # Import NumPy for random number generation
import pylab  # Import Pylab (part of matplotlib for plotting)
import scipy.cluster.hierarchy as sch  # Import hierarchical clustering methods from SciPy

# Generate random features (1D array of 40 elements) and initialize a distance matrix.
x = np.random.rand(40)  # Create a random array of 40 elements using NumPy
D = np.zeros([40, 40])  # Initialize a 40x40 zero matrix to store distances

# Populate the distance matrix by calculating the absolute differences between the elements.
for i in range(40):
    for j in range(40):
        D[i, j] = abs(x[i] - x[j])  # Compute the absolute difference between points

# Create the figure and plot the first dendrogram.
fig = pylab.figure(figsize=(8, 8))  # Create an 8x8 inch figure
ax1 = fig.add_axes([0.09, 0.1, 0.2, 0.6])  # Add the first subplot for the first dendrogram

# Perform hierarchical clustering using the 'centroid' method and plot the first dendrogram.
Y = sch.linkage(D, method='centroid')  # Compute the hierarchical clustering with centroid linkage
Z1 = sch.dendrogram(Y, orientation='right')  # Generate the dendrogram with 'right' orientation
ax1.set_xticks([])  # Remove x-axis ticks
ax1.set_yticks([])  # Remove y-axis ticks

# Compute and plot the second dendrogram.
ax2 = fig.add_axes([0.3, 0.71, 0.6, 0.2])  # Add the second subplot for the second dendrogram
Y = sch.linkage(D, method='single')  # Perform hierarchical clustering using the 'single' linkage method
Z2 = sch.dendrogram(Y)  # Generate the dendrogram (default orientation)
ax2.set_xticks([])  # Remove x-axis ticks
ax2.set_yticks([])  # Remove y-axis ticks

# Reorder and plot the distance matrix according to the dendrogram's leaf order.
axmatrix = fig.add_axes([0.3, 0.1, 0.6, 0.6])  # Add the main subplot for the reordered distance matrix
idx1 = Z1['leaves']  # Get the order of leaves from the first dendrogram
idx2 = Z2['leaves']  # Get the order of leaves from the second dendrogram
D = D[idx1, :]  # Reorder rows of the distance matrix based on the first dendrogram
D = D[:, idx2]  # Reorder columns of the distance matrix based on the second dendrogram
im = axmatrix.matshow(D, aspect='auto', origin='lower', cmap=pylab.cm.YlGnBu)  # Plot the reordered matrix with color

# Remove ticks for the matrix plot.
axmatrix.set_xticks([])  # Remove x-axis ticks
axmatrix.set_yticks([])  # Remove y-axis ticks

# Add a colorbar to show the scale of the distances.
axcolor = fig.add_axes([0.91, 0.1, 0.02, 0.6])  # Add an axis for the colorbar
pylab.colorbar(im, cax=axcolor)  # Create and add the colorbar

# Display the plot and save it as an image.
fig.savefig('dendrogram_example_02.png')  # Save the figure as a PNG file
fig.show()  # Display the figure

Comment créer un dendrogramme en Python avec scipy et matplotlib ?
Comment créer un dendrogramme en Python avec scipy et matplotlib ?

Références

Image

of