Fonction pour diagramme à l'aide de panda python

Flo -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -
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 ????

3 réponses

  1. merle_taquin
     
    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
    1. Flo
       
      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
  2. merle_rigolo
     
    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
  3. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 940
     
    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