Fonction pour diagramme à l'aide de panda python

Fermé
Flo - Modifié le 4 juil. 2022 à 16:46
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 - 4 juil. 2022 à 16:43
Bonjour a tous,

Je débute en développement python et n'arrive pas à régler un problème sur mon code.

A partir d'un tableau panda, je souhaiterai faire ressortir plusieurs diagrammes grâce à une fonction mais je rencontre malheureusement une erreur. Elle ne fonctionne que pour un seul paramètre. Je pense que le problème vient de l'index de chaque dictionnaire que je fais à partir du tableau, malheureusement je ne trouve pas de solution pour modifier celui-ci.

Voici mon code :

def graphic_movie(film):
  
  df_film = df2 [df2['film'] == film]

  insulte = df_film['jurons']
  data2 = df_film['minutes_simples']
  
  res = {
    key : [
      insulte[idx]
      for idx in range(len(insulte))
      if data2[idx] == key
    ] 
    for key in set(data2)
  } 
  print(res)

  A = []
  B = []
  C = []

  for cle in res.keys():
    A.append(cle)

  for valeur in res.values(): 
    B.append(valeur.count('insult'))
    C.append(valeur.count('mort'))
 
  plt.bar(A, B, color = "blue")
  plt.bar(A, C, bottom = np.array(B), color = "red")
  plt.ylim([0, 20])


L'erreur recue est : KeyError: 0.

Si une âme charitable a une solution à me proposer. Merci ????
A voir également:

3 réponses

merle_taquin
30 juin 2022 à 07:43
Bonjour, pour faire avancer le schmilblick, qu'est censé faire cette ligne
df_film = df2 [df2['film'] == film]
?

Parce que là, on obtient un booléen, donc df2[True] (ou False), on imagine que tu n'as pas cette clé dans ton dictionnaire.

Donner l'erreur que python renvoie, c'est bien, seulement, il faudrait montrer l'erreur entière qu'il renvoie, ainsi que la ligne de code où se situe cette erreur.
0
Merci de ta réponse !

Effectivement, j'ai ajouté suffisamment d'information.
Cette ligne me permet de sélectionner uniquement le film qui m’intéresse pour en récupérer les valeurs associées.


               film  minutes_simples  jurons
0     Reservoir Dogs              0.0  insult
1     Reservoir Dogs              0.0  insult
2     Reservoir Dogs              1.0  insult
3     Reservoir Dogs              1.0  insult
4     Reservoir Dogs              1.0  insult
...              ...              ...     ...
1889    Jackie Brown            142.0  insult
1890    Jackie Brown            142.0  insult
1891    Jackie Brown            142.0  insult
1892    Jackie Brown            143.0  insult
1893    Jackie Brown            143.0    mort

[1894 rows x 3 columns]


Du coté de l’erreur complète :

KeyError                                  Traceback (most recent call last)

/usr/local/lib/python3.7/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
3360 try:
-> 3361 return self._engine.get_loc(casted_key)
3362 except KeyError as err:

8 frames

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()

KeyError: 0


The above exception was the direct cause of the following exception:

KeyError Traceback (most recent call last)

/usr/local/lib/python3.7/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
3361 return self._engine.get_loc(casted_key)
3362 except KeyError as err:
-> 3363 raise KeyError(key) from err
3364
3365 if is_scalar(key) and isna(key) and not self.hasnans:

KeyError: 0
0
Comme ça, je ne vois pas trop, de plus aucune ligne de ton code est incriminée dans le traceback de l'erreur, bizarre.

De toute façon, je ne comprends pas ton code, si la liste df2 est la liste présentée au-dessus, alors pourquoi df_film serait uniquement un des 2 premiers de ton dictionnaire ? Je pense ne pas avoir compris ce qu'est supposé faire ton code au départ avec toutes tes listes.

Et si ce que je suppute est juste, alors forcément res ne contiendrait (?) qu'un seul item. Est-ce le cas ? vu que tu fais un print de ce dico.

Et si tu ne sais pas où se situe l'erreur dans ton code, reste à mettre des print après chaque instruction pour au moins voir ce qui déconne.

Bon courage.
0
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
Modifié le 4 juil. 2022 à 18:24
Bonjour,

Merci quand tu partages du code de faire en sorte qu'il soit reproductible, minimal, et déclenche le problème. Voici un code qui reproduit ton problème. N'oublie d'expliquer le but recherché.

Reformulation de la question

import re
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

def graphic_movie(film):
    df_film = df2[df2['film'] == film]
    insulte = df_film['jurons']
    data2 = df_film['minutes_simples']
    
    res = {
        key : [
            insulte[idx]
            for idx in range(len(insulte))
            if data2[idx] == key
        ] 
        for key in set(data2)
    }
    A = []
    B = []
    C = []
    for cle in res.keys():
        A.append(cle)
    for valeur in res.values(): 
        B.append(valeur.count('insult'))
        C.append(valeur.count('mort'))        
    plt.bar(A, B, color = "blue")
    plt.bar(A, C, bottom = np.array(B), color = "red")
    plt.ylim([0, 20])
    
text = """0     Reservoir Dogs              0.0  insult
1     Reservoir Dogs              0.0  insult
2     Reservoir Dogs              1.0  insult
3     Reservoir Dogs              1.0  insult
4     Reservoir Dogs              1.0  insult
1889    Jackie Brown            142.0  insult
1890    Jackie Brown            142.0  insult
1891    Jackie Brown            142.0  insult
1892    Jackie Brown            143.0  insult
1893    Jackie Brown            143.0    mort"""

df2 = pd.DataFrame(
    [
        re.split("\s\s+", line)
        for line in text.splitlines()
    ],
    columns=["index", "film", "minutes_simples", "jurons"]
)

for film in "Reservoir Dogs", "Jackie Brown":
    graphic_movie(film)


Si j'ai bien compris, on veut tracer le nombre d'occurrence d'un juron (
insult
ou
mort
dans ton jeu d'exemple) au court du temps.

Retour au problème

Le code plante au moment de construire
res
(en fonction du film). Je te propose deux solutions :

En pandas et pyplot

import re
import pandas as pd
import matplotlib.pyplot as plt
    
text = """0     Reservoir Dogs              0.0  insult
1     Reservoir Dogs              0.0  insult
2     Reservoir Dogs              1.0  insult
3     Reservoir Dogs              1.0  insult
4     Reservoir Dogs              1.0  insult
1889    Jackie Brown            142.0  insult
1890    Jackie Brown            142.0  insult
1891    Jackie Brown            142.0  insult
1892    Jackie Brown            143.0  insult
1893    Jackie Brown            143.0    mort"""

df2 = pd.DataFrame(
    [
        re.split("\s\s+", line)
        for line in text.splitlines()
    ],
    columns=["index", "film", "minutes_simples", "jurons"]
)

for film in sorted(set(df2["film"])):
    df_film = df2[df2["film"] == film]
    jurons = set(df_film["jurons"])
    for juron in jurons:
        agg = df_film[df_film["jurons"] == juron].groupby("minutes_simples")
        map_minute_num = {
            minute : len(indices)
            for minute, indices in agg.groups.items()
        }
        print(film, juron, map_minute_num)
        X = sorted(map_minute_num.keys())
        Y = [map_minute_num[x] for x in X]
        plt.bar(X, Y, color = "blue")
        plt.ylim([0, 20])
        plt.show()


Résultat :

Jackie Brown insult {'142.0': 3, '143.0': 1}
Jackie Brown mort {'143.0': 1}
Reservoir Dogs insult {'0.0': 2, '1.0': 3}

En pandas pur

import re
import pandas as pd
    
text = """0     Reservoir Dogs              0.0  insult
1     Reservoir Dogs              0.0  insult
2     Reservoir Dogs              1.0  insult
3     Reservoir Dogs              1.0  insult
4     Reservoir Dogs              1.0  insult
1889    Jackie Brown            142.0  insult
1890    Jackie Brown            142.0  insult
1891    Jackie Brown            142.0  insult
1892    Jackie Brown            143.0  insult
1893    Jackie Brown            143.0    mort"""

df2 = pd.DataFrame(
    [
        re.split("\s\s+", line)
        for line in text.splitlines()
    ],
    columns=["index", "film", "minutes_simples", "jurons"]
)

for film in sorted(set(df2["film"])):
    df_film = df2[df2["film"] == film]
    df_film["minutes_simples"].hist(by=df_film["jurons"])


Plus de détails ici

Bonne chance
0