Heatmap avec courbes de tendances dans chaque case de la map

Fermé
Qunqun. Messages postés 173 Date d'inscription vendredi 24 février 2017 Statut Membre Dernière intervention 9 mars 2023 - 28 févr. 2023 à 11:21
mamiemando Messages postés 32974 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 mars 2024 - 9 mars 2023 à 15:24

Bonjour à tous

Je cherche à faire un script python qui analyse les données d'un fichier json. Le fichier nous donne entre autre une liste de musiques lues et à quelle date.

J'ai réussi avec seaborn et matplotlib à créer une heatmap qui représente la quantité de musiques lues en fonction de l'heure du jour dans la semaine, pour toutes les musiques lues depuis environ 2018 jusqu'à 2023. (pour le contexte)

J'ai de même réussi à tracer une courbe d'évolution des lectures, qui m'indique en fonction du temps la quantité de musiques lues. (pour le contexte, je peux donc voir que globalement, j'écoute de plus en plus de musique)

J'aimerais maintenant cumuler les deux graphiques, et afficher une courbe de tendances pour chaque case de la heatmap, ce qui me permettrait de voir si les musiques lues à une certaine heure de la journée témoignent d'une véritable habitude sur le long terme, ou bien si ces valeurs ont été faites sur une période courte et non habituelle.

Pour ça, j'ai fait un tableau tableau=[[[0] * 30] * 24] * 7 (avec 30 le nombre de points à afficher sur la courbe, donc une "précision" dans laquelle j'entre le nombre de lectures comptées pour une période de temps fixe, pour chaque heure ; 24 et 7 les 24h de la journée et les 7 jours de la semaine)

J'arrive bien à compléter mon tableau, il semble cohérent, je peux donc tracer chacune des courbes associées à chacune des cases de la heatmap. Mais la partie plus délicate arrive maintenant, je ne parviens pas à superposer ces courbes et les afficher toutes ensemble sur la heatmap.

Ma première question est simple, est-ce possible ? :D

Et la deuxième question, est-ce que vous avez des pistes ou des idées sur la façon de faire pour tracer ce que je veux ?

En espérant que mes explications soient suffisamment claires, merci d'avance pour vos réponses et les pistes que vous pourriez me donner ;)

Bonne journée !

A voir également:

1 réponse

mamiemando Messages postés 32974 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 mars 2024 7 728
28 févr. 2023 à 20:43

Bonjour,

Qu'entends-tu par superposer les courbes ? Cherches tu as faire des sous-figures ? Note que tu peux parfaitement créer des sous-figures qui impliques des images de différentes natures (graphes, images, etc.)

Ce que je te recommande c'est d'utiliser gridspec.

import matplotlib.pyplot as plt

fig = plt.figure()
gs = fig.add_gridspec(2, 3) # Créer une grille de 2x3 graphes
plt.subplots_adjust(wspace=0.5, hspace=0.5)

for i in range(2):
    for j in range(3):
        ax = fig.add_subplot(gs[i, j])
        ax.set_title(f"Graphe (i, j)")

plt.show()

Bonne chance

0
Qunqun. Messages postés 173 Date d'inscription vendredi 24 février 2017 Statut Membre Dernière intervention 9 mars 2023 46
1 mars 2023 à 14:50

Merci beaucoup pour ta réponse !

Quand je dis superposer, c'est ajouter au dessus de ma heatmap d'autres courbes, faire une grille de sous figures. En effet, ta suggestion ressemble bien à ce que je veux faire, il faut maintenant que j'ajuste à mes besoins, je vais fouiller un peu et je vous tiendrai au courant !
Un exemple quand même de ce que je voudrais en image, j'arrive à avoir la heatmap d'arrière plan, maintenant il faut ajouter ces courbes par dessus... Au boulot :)

0
Qunqun. Messages postés 173 Date d'inscription vendredi 24 février 2017 Statut Membre Dernière intervention 9 mars 2023 46
Modifié le 2 mars 2023 à 15:30

Bonjour :)

Je reviens à la charge après un peu de recherches. En effet, gridspec était une bonne idée, qui m'a permis d'avancer un peu.
J'ai maintenant ma grille de graphiques comme ceci :

J'ai de même ma heatmap comme ceci :

Cependant, les deux figures s'affichent sur une fenêtre séparée, au lieu de se superposer :/
Est-il possible d'afficher les deux figures ensemble, sans qu'elles ne prennent simplement une zone à gauche pour un graphe, et l'autre à droite ? Il me semble avoir vu qu'on pouvait utiliser les axes d'une figure pour en afficher une seconde, mais ceci ne me donne que deux fenêtres distinctes, je dois me tromper dans ma compréhension du mécanisme...

Voici l'extrait de code qui me permet d'arriver à ceci, peut-être qu'il donnera plus d'indications ?

# Créer la heatmap avec seaborn
# days_labels, hours_labels, heatmap_data et heatmap_graph on été initialisées plus haut, et contiennent les données nécessaires à l'exécution du programme
fig = plt.figure(figsize=(10, 7))
ax = fig.subplots()
heatmap = sns.heatmap(heatmap_data, cmap='Reds', cbar_kws={'label': "Quantité d'écoute"}, annot=True, fmt='.0f')
heatmap.set_yticklabels(days_labels, rotation=0)
heatmap.set_xticklabels(hours_labels, rotation=0)
plt.title("Quantité d'écoute sur les créneaux horaires de la semaine")
plt.xlabel("Heures de la journée")
plt.ylabel("Jours de la semaine")


jours = 7
heures = 24
# Récupération de la valeur la plus haute pour générer une limite verticale d'échelle pour les graphes
max_value = heatmap_graph[0][0][0]
for i in range(7):
    for j in range(24):
        for k in range(precision):
            if heatmap_graph[i][j][k] > max_value:
                max_value = heatmap_graph[i][j][k]

fig = plt.figure(figsize=(10, 7))
gs = fig.add_gridspec(jours, heures, hspace=0, wspace=0) # Créer une grille de 7*24 sans espacement
for i in range(jours):
    for j in range(heures):
        ax = fig.add_subplot(gs[i, j])
        ax.set_xticks([])
        ax.set_yticks([])
        ax.set_xlabel('')
        ax.set_ylabel('')
        ax.set_ylim(ymin=-5, ymax=max_value + 5)  # Définir les même limites pour chaque graphique
        ax.plot(dates_list, heatmap_graph[i][j])

plt.show()

Merci pour votre aide, et dans l'attente de vos conseils et suggestions :)

0
mamiemando Messages postés 32974 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 mars 2024 7 728 > Qunqun. Messages postés 173 Date d'inscription vendredi 24 février 2017 Statut Membre Dernière intervention 9 mars 2023
Modifié le 3 mars 2023 à 15:16

Bonjour,

  • Le terme "superposer" est ambigu car pour moi ça veut dire mettre l'un par dessus l'autre, or dans ton cas j'ai l'impression que tu veux mettre ta heatmap et tes plots l'un au dessus de l'autre (ou l'un à côté de l'autre ?).
  • De ce que je comprends de ton code, tu organises dans une grille 7x24 un ensemble de heatmaps (une par jour et par heure).
  • Si j'ai bien compris tu voudrais imbriquer deux grilles : la première permet de positionner les plots et les heatmaps dans la même figure, et ensuite dans chacune de ces "cases", tu as une sous-grille (respectivement notamment une grille 7x24 pour les heatmaps et une grille 7x1 pour tes graphes). Si c'est bien ça, je te renvoie à ce tutoriel.

Bonne chance

0
Qunqun. Messages postés 173 Date d'inscription vendredi 24 février 2017 Statut Membre Dernière intervention 9 mars 2023 46 > mamiemando Messages postés 32974 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 mars 2024
9 mars 2023 à 14:56

Désolé pour mon retour tardif :/

Merci pour ta réponse !

"Superposer" pour moi veut dire obtenir les deux figures que j'ai actuellement (la heatmap de couleurs en 7*24 cases, et l'ensemble des 7*24 courbes disposées en grille) en une seule figure, l'une par dessus l'autre, pour donner un rendu comme l'illustration que j'ai donné sur mon message du 1er mars.
J'arrive pour le moment à avoir deux figures sur deux fenêtres séparées, ou au mieux 2 figures sur une seule fenêtre, mais l'une à côté de l'autre, je n'arrive cependant pas à obtenir ce rendu :/

J'ai regardé le tuto, et je crois ne pas en saisir toutes les nuances, je parviens à l'utiliser correctement pour faire la grille de 7*24 courbes les unes à côté des autres, cependant impossible d'utiliser cette grille une fois faite pour la placer par au dessus de la heatmap /superposer les deux figures / imbriquer la grille dans la heatmap...

Merci pour ton retour et tes conseils :)

0
mamiemando Messages postés 32974 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 2 mars 2024 7 728 > Qunqun. Messages postés 173 Date d'inscription vendredi 24 février 2017 Statut Membre Dernière intervention 9 mars 2023
9 mars 2023 à 15:24

Il faudrait que tu me partages ton code avec les gridspec, mais en gros, si je reprends le lien précédent, en adaptant gs0, on arrive bien à mettre les deux gridspecs l'une au dessus de l'autre :

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec


def format_axes(fig):
    for i, ax in enumerate(fig.axes):
        ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center")
        ax.tick_params(labelbottom=False, labelleft=False)


# gridspec inside gridspec
fig = plt.figure()

gs0 = gridspec.GridSpec(2, 1, figure=fig)

gs00 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0])

ax1 = fig.add_subplot(gs00[:-1, :])
ax2 = fig.add_subplot(gs00[-1, :-1])
ax3 = fig.add_subplot(gs00[-1, -1])

# the following syntax does the same as the GridSpecFromSubplotSpec call above:
gs01 = gs0[1].subgridspec(3, 3)

ax4 = fig.add_subplot(gs01[:, :-1])
ax5 = fig.add_subplot(gs01[:-1, -1])
ax6 = fig.add_subplot(gs01[-1, -1])

plt.suptitle("GridSpec Inside GridSpec")
format_axes(fig)

plt.show()

Bonne chance

0