IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

opérations sur listes et dictionnaires


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Par défaut opérations sur listes et dictionnaires
    Bonjour à tous, je débute depuis peu sur Python et j'ai un problème pour traiter des listes et dictionnaires.

    Voici le topo:
    j'ai un dictionnaire avec 2 clés :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d={'Ei' : des_valeurs , 'id': des_identifiants}
    Certains identifiants sont identiques et j'aimerai faire une boucle qui passe tous les éléments de 'id'. Tant que les id sont identiques il faudrait mettre leur valeur (récupérée dans 'Ei' avec l'indice) dans une liste.
    Lorsque tous les id identiques sont dans la liste, on fait la moyenne de leur valeur Ei
    Une fois ceci fait il faudrait repartir sur une seconde série de id identiques

    Un exemple pour être plus clair :p :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d= {'Ei': 1,3,4,4,6 , 'id' : 'r','r','t','t','t'}
    Ce que j'aimerai c'est passer id, prendre tous les 'r' et mettre leur valeur Ei dans une liste temporaire v:
    ensuite je fais un traitement sur v (moyenne) et après on repart sur le reste des id:
    tous les 't':
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    v=[]
    v.append(4,4,6)...
    j'ai essayé avec de boucles while ou avec un for mais je n'arrive pas à m'en sortir. Même chose quand j'essaye
    ca m'embarque dans des trcus que je n'arrive pas à finaliser


    Merci et j'espère avoir été a peu près clair

  2. #2
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    Avec quelle version de python travailles-tu?
    Chez moi (2.6) la ligne:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    d= {'Ei': 1,3,4,4,6 , 'id' : 'r','r','t','t','t'}
    ne passe pas.
    par contre:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
    est admise
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  3. #3
    Membre averti
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Par défaut
    Bonjour,

    oui oui tu as raison c'est moi qui est oublié les parenthèses ! Sorry
    (je suis aussi en 2.6)

    Mis à part ça est ce que ce que j'ai raconté est compréhensible ?

    merci

  4. #4
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
    L=[(d['id'][i],d['Ei'][i]) for i in xrange(0,len(d['Ei']))]
    R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
    print R
    résultat:
    [('r', [1, 3]), ('t', [4, 4, 6])]
    Is that what you want ?
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  5. #5
    Membre averti
    Inscrit en
    Août 2010
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 27
    Par défaut
    whaooooo ... les bras m'en tombent !
    C'est beau ca !

    Je le teste et je reviens te dire si ca fonctionne avec tout mon jeu de données.

    merci en tous cas !

  6. #6
    Membre chevronné
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Par défaut
    Une version avec le module itertools:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    from itertools import groupby
     
    d = {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
     
    result = []
    # Retourne les éléments associés à 'r' et à 't'
    for key, group in groupby(zip(d['id'], d['Ei']), lambda x: x[0]):
           # Pour 'r' et 't' on ajoute les éléments retourner par le groupage
           result .append((key, [thing[1] for thing in group]))
     
    print result
    Pas sur que cette solution apporte grand chose de plus, mias ça m'a fait réviser itertools...

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Zavonen, ta solution présente deux inconvénients:


    - perte de l’ordre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    d= {'Ei': (1,3,22,40,40,60,4000,5000) ,
        'id' : ('r','r','x','t','t','t','a','a')}
    L=zip(d['id'],d['Ei'])
    R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
    print 'R =',R
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    R = [('a', [4000, 5000]), ('x', [22]), ('r', [1, 3]), ('t', [40, 40, 60])]

    - mélange de toutes les occurences dans d[’id’], même non contigues:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    d= {'Ei': (1,3,40,40,60,700,900,3000) ,
        'id' : ('riz','riz','t','t','t','riz','riz','a')}
    L=zip(d['id'],d['Ei'])
    R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
    print 'R =',R
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    R = [('a', [3000]), ('riz', [1, 3, 700, 900]), ('t', [40, 40, 60])]


    Mais ça n’a peut être pas d’importance pour l’application de rom44.








    J’ai d’abord pensé aussi à groupby(iterable[, key]) , mais sans utliser key égale à lambda x: x[0] je ne suis arrivé à rien.

    J’ai donc écrit une fonction génératrice:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def f_moy(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,sum(d['Ei'][jprec:j])/(j-jprec)
                jprec,idprec = j,idx
                yield y
        j+=1
        yield d['id'][-1],sum(d['Ei'][jprec:j])/(j-jprec)


    Cette fonction donne les moyennes, puisque c’est ce que vise rom44.





    --------------------------------------------------



    Ta solution est concise, datah, surtout si on l’écrit sous forme de list comprehension.
    Mais elle a deux inconvénients:


    1) elle est plus lente:

    Pour comparer , j’ai réécrit ma fonction pour qu’elle donne les groupes.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    from time import clock
    from itertools import groupby
     
    d = {'Ei': (1,3,4,4,6,70,80,2000,3000,4000,6000,1111,2222,
                23,13,43,53,63,733,93,83,13,33,65,75,85) ,
         'id' : ('r','r','t','t','t','r','r','b','b','b','b','x','y',
                 'a','a','a','a','a','a','a','a','a','a','r','r','r')}
     
    t0 = clock()
    for x in xrange(10000):
        result = [ (key, [thing[1] for thing in group])
                 for key, group in groupby(zip(d['id'], d['Ei']), lambda x: x[0]) ]
    dt = clock()-t0
    print dt
    print result
     
    print '\n'
     
     
    def f_group(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,d['Ei'][jprec:j]
                jprec,idprec = j,idx
                yield y
        j+=1
        yield d['id'][-1],d['Ei'][jprec:j]
     
     
    t0 = clock()
    for x in xrange(10000):
        resf = f_group(d)
    dt = clock()-t0
    print dt
    print [u for u in f_group(d)]
    Résultat: la version avec groupby() prend 27 fois le temps de la fonction f_group().




    2) groupby() renvoit un itérateur qui débite des éléments (k,group) dont group est lui même un itérateur.

    Or si on fait sum(group) , on épuise l’itérateur, c’est à dire que len(group) ne donnera ensuite pas de valeur. Ce qui n’est pas pratique pour calculer la moyenne de chaque groupe, qui est le centre d’intérêt de rom44.

    Pour pallier à cette insuffisance, il faut enregistrer l’objet list(group) ou tuple(group). De ce fait on ne peut plus utiliser une list comprehension.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    from time import clock
    from itertools import groupby
     
    d = {'Ei': (1,3,4,4,6,70,80,2000,3000,4000,6000,1111,2222,
                23,13,43,53,63,733,93,83,13,33,65,75,85) ,
         'id' : ('r','r','t','t','t','r','r','b','b','b','b','x','y',
                 'a','a','a','a','a','a','a','a','a','a','r','r','r')}
     
    to = clock()
    for x in xrange(10000):
        result = []
        # Retourne les éléments associés à 'r' et à 't'
        for key, group in groupby(zip(d['id'], d['Ei']), lambda x: x[0]):
               # Pour 'r' et 't' on ajoute les éléments retourner par le groupage
               gr = tuple(group)
               result.append((key, sum(thing[1] for thing in gr)/len(gr)))
    dt = clock()-t0
    print dt
    print result
     
    print '\n'
     
     
    def f_moy(d):
        jprec,idprec = 0,d['id'][0]
        for j,idx in enumerate(d['id']):
            if idx!=idprec:
                y = idprec,sum(d['Ei'][jprec:j])/(j-jprec)
                jprec,idprec = j,idx
                yield y
        j+=1
        yield d['id'][-1],sum(d['Ei'][jprec:j])/(j-jprec)
     
    t0 = clock()
    for x in xrange(10000):
        resf = f_moy(d)
    dt = clock()-t0
    print dt
    print [u for u in f_moy(d)]
    Ce faisant, le temps d’exécution de la méthode avec groupby() augmente: il est multiplié par 2,5 tandis que la méthode avec la fonction génératrice f_moy() voit son temps augmenter d’à peine 1 ou 2 %.

    Ce qui au final fait qe la méthode avec groupby() et renvoi des moyennes met 65 fois plus de temps que la fonction f_moy().

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [AC-2013] Opérations sur un champ Liste de choix automatique
    Par frieden dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 04/06/2015, 19h23
  2. opération sur deux listes
    Par simnitch dans le forum Lisp
    Réponses: 7
    Dernier message: 24/04/2013, 10h12
  3. Opérations sur des morceaux de liste
    Par edding4 dans le forum Général Python
    Réponses: 7
    Dernier message: 10/10/2011, 15h47
  4. Opération sur liste
    Par jouclar dans le forum Général Python
    Réponses: 4
    Dernier message: 24/05/2011, 19h17
  5. [langage] random sur liste ou tableau
    Par martijan dans le forum Langage
    Réponses: 2
    Dernier message: 15/07/2003, 14h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo