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

Calcul scientifique Python Discussion :

[Pandas] [Itertools] optimisation d'un code pour remplir un dataframe par une combinaison


Sujet :

Calcul scientifique Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 61
    Points : 33
    Points
    33
    Par défaut [Pandas] [Itertools] optimisation d'un code pour remplir un dataframe par une combinaison
    Bonjour à tous,
    j'ai découvert les librairies itertools et Pandas depuis 2 jours, j'ai écrit un bout de code qui répond à mes attentes mais l'exécution est beaucoup trop longue.

    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
    from itertools import *
    import pandas as pd
     
    items = [1,2,3,4,5,6,7,8,9,10,11,12]
    data = [200,250,190,0,132,149,168,0,198,184,176,203]
    colonnes = ["Combinaison","Nb","Total","Min","Max","Ecart"]
    df = pd.DataFrame(columns = colonnes)
    i = 0
    for y in range(5,10):
        for c in combinations(items, y):
            Somme = 0
            Mini = 0
            Maxi = 0
            for a in c :
                Somme += data[a-1]
                if Mini == 0 or Mini > data[a-1] :
                    Mini = data[a-1]
                if Maxi < data[a-1] :
                    Maxi = data[a-1]
            ligne = (c,y,Somme,Mini,Maxi,Maxi-Mini)
            df.loc[i] = ligne
            i += 1   	
    print(df)
    Le but de ce bout de code:
    - je vais donner une série variable de 10 à 12 poids stockés dans la variable data (j'ai mis des données fictives pour faire les essais)
    - Je demande de calculer toutes les combinaisons de 5 , 6 , 7 , 8 et 9 nombres ainsi que la somme, le minimum, le maximum et l'écart maxi pour chacune de ces combinaisons.
    - je souhaite ensuite remplir à la volée un dataframe avec les 3223 combinaisons possibles. Mais comme je le remplis une ligne à la fois c'est très long. Comment puis-je optimiser l'insertion de ces données dans le dataframe alors que j'ai des opérations à réaliser sur chaque combinaison pour définir la somme, le mini et le maxi

    Merci d'avance de votre aide

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Bonjour,

    Ce qui est très lent, c'est l'agrandissement du Dataframe une ligne à la fois.

    Il vaut mieux collecter toutes les lignes dans une liste et créer le Dataframe en une fois:
    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
    from itertools import *
    import pandas as pd
     
    items = [1,2,3,4,5,6,7,8,9,10,11,12]
    data = [200,250,190,0,132,149,168,0,198,184,176,203]
    colonnes = ["Combinaison","Nb","Total","Min","Max","Ecart"]
    i = 0
    lignes = []
    for y in range(5,10):
        for c in combinations(items, y):
            Somme = 0
            Mini = 0
            Maxi = 0
            for a in c :
                Somme += data[a-1]
                if Mini == 0 or Mini > data[a-1] :
                    Mini = data[a-1]
                if Maxi < data[a-1] :
                    Maxi = data[a-1]
            ligne = (c,y,Somme,Mini,Maxi,Maxi-Mini)
            lignes.append(ligne)
            i += 1       
    df = pd.DataFrame(data = lignes, columns = colonnes)
    print(df)

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Charge Etudes Statistiques
    Inscrit en
    Avril 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Charge Etudes Statistiques

    Informations forums :
    Inscription : Avril 2016
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Bonjour,

    En créant le Dataframe à la fin, le traitement tourne plus rapidement.
    Par contre dans les deux cas, je retrouve sur la première ligne la colonne Min=132, elle ne devrait pas être égale à 0 ? (J'ai l'impression quelle est toujours égale à la dernière valeur)

    Alternative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import itertools as ite
    import pandas as pd
     
    items=[1,2,3,4,5,6,7,8,9,10,11,12]
    data = [200,250,190,0,132,149,168,0,198,184,176,203]
     
    result=[(combi,len(da),sum(da),min(da),max(da)) 
            for nbCombi in range(5,10) 
                   for combi,da in zip(ite.combinations(items, nbCombi),ite.combinations(data, nbCombi))]
     
    df=pd.DataFrame(result,columns=["Combinaison","Nb","Poids","Min","Max"])
    df['Ecart']=df['Min']-df['Max']
    print(df.head())

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 61
    Points : 33
    Points
    33
    Par défaut
    Bonsoir,
    tout d'abord merci à vous deux de m'avoir consacrer un peu de temps pour mes "débuts" sur Python. J'ai déjà appris certaines choses!

    Je pense utiliser la solution de Datasteo car je pense que les fonctions de min, max, sum et len d'itertools doivent être plus optimisées que mes calculs.

    Ensuite comme vous avez l'air au taquet sur ce sujet, j'ai une petite question:
    dans mon cas actuellement j'utilise 2 listes de données (items et data) étant donné que j'ai besoin de connaitre les identifiants des différentes sources des données. Donc ca nécessite 2 opérations pour calculer les combinaisons (l'une sur les identifiants, l'autre sur les données).
    Sur ce projet j'ai vraiment besoin d'optimiser le temps d’exécution de la fonction je me demande s'il n'est pas possible de tout faire sur un seul calcul de combinaison.
    je m'explique:
    dans mon exemple j'ai:
    data = [200,250,190,0,132,149,168,0,198,184,176,203]
    En réalité, les nombre de données que je vais envoyer à cette fonction sera variable: les 0, je n'en ai pas besoin dans mon calcul de combinaison, donc on peut, peut être, ignorer cette donnée au moment du calcul de toutes les combinaisons possibles.... Par contre , j'ai obligatoirement besoin de connaitre la position de chaque chiffre dans la liste initiale ...
    Alors est ce que intertools, peut ignorer les 0 dans le listage des combinaisons? Est-ce qu'Intertools est capable de donner la position des données utilisées pour chacune des combinaison. A ce moment là je n'ai plus besoin de ma liste "items".

    J'espère que vous m'avez compris.

    Merci encore

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Quand il s'agit d'optimisation, le maître-mot n'est pas "penser" mais "mesurer". Le code de Datasteo est élégant est efficace, et il corrige le bug mentionné sur le min (bug lié à l'utilisation d'une valeur sentinelle qui se trouve dans les données) que je n'avais pas relevé. Petit détail: Les fonctions min, max, sum et len sont des fonctions builtin en Python, elles n'appartiennent pas à itertools.

    Note que mon code est déjà environ 600 fois plus rapide que ton code initial, dans mes tests, et celui de Datasteo est sans doute encore un peu plus efficace.

    Je ne pense pas que tu puisses te passer efficacement de la liste items. Tu pourrais "zipper" les deux listes afin de n'appeler qu'une seule fois itertools.combinations mais cela ne t'apportera sans doute rien.

    Par contre, si les 0 ne t'intéressent pas, tu peux toujours les supprimer de data (en supprimant l'élément correspondant de items) avant de calculer les combinaisons, ça devrait faire une grosse différence. En reprenant ton exemple, cela fait passer le nombre de combinaisons de 3223 à 637, un gain d'un facteur 5.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 61
    Points : 33
    Points
    33
    Par défaut
    Petit up pour une petite question.

    Le code fonctionne toujours super bien mais je souhaite faire évoluer quelques petites choses.
    Je sais trier des dataframes en fonction des valeurs mais est-ce possible d'écarter certaines combinaisons en fonction de certains items?

    Je n'ose pas manipuler la colonne combinaison parce que si je trie les résultats dont la combinaison contient "1" il va me virer aussi le 10 , 11 ,12?
    Comment puis-je m'y prendre svp?

    Merci d'avance

Discussions similaires

  1. [Débutant] Code c# : pour remplir (combobox) à partir d'une BDD postgresql
    Par geoinformation dans le forum C#
    Réponses: 11
    Dernier message: 22/12/2012, 13h53
  2. Problème avec un code pour remplir une feuille de calcul
    Par NEC14 dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 31/03/2011, 23h17
  3. Réponses: 8
    Dernier message: 10/09/2010, 16h19
  4. Code pour remplir deux listes liées
    Par nb-wissam dans le forum Forms
    Réponses: 4
    Dernier message: 16/06/2010, 16h43
  5. problème code pour remplir un fichier Excel
    Par ririrourou dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 18/07/2008, 10h51

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