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 :

Création d'une colonne dasn un dataframe sous condition en utilisant la fonction eval [Python 3.X]


Sujet :

Python

  1. #1
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut Création d'une colonne dasn un dataframe sous condition en utilisant la fonction eval
    Bonjour,

    Je me prends la tête depuis hier et je ne trouve pas de solution satisfaisante.

    J'ai récupéré des données de tirs en biathlon qui sont sous ce format:

    Pour l'exercice à deux tirs : 2+3
    Pour l'exercice à quatre tirs : 0+3+1+2

    Je souhaite déterminer le pourcentage de réussite de chaque athlète (pour un exercice à deux tirs 100% de réussite c'est 0+0)

    Nom : données.png
Affichages : 212
Taille : 140,7 Ko

    j'ai tenté de faire une boucle... mais c'est hyper long et ça ne fonctionne pas la colonne statistique de tir est vide

    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
     for index, row in data_all.iterrows():
        #exercice à deux tirs
        try:
            if len(row.Shootings)==3 | len(row.Shootings)==4:
                tirs_rat= eval(row.Shootings)
                if tirs_rat <=10:
                        row.Shootings_stats = ((-10*tirs_rat) +100)
            elif len(row.Shootings)==7:
                tirs_rat=eval(row.Shootings)
                if tirs_rat <=20:
                        row.Shootings_stats = ((-5*tirs_rat) +100)
                        print(row.Shootings_stats)
        except (RuntimeError, TypeError, NameError):
            Shootings_stats_calc.append('NA')
            pass
     
     
    print(data_all.Shootings_stats)

    J'ai aussi tenté ce genre de chose mais cela ne fonctionne pas non plus:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    data_all['Shootings_stats']=[(-(eval(str(x))*10 +100)) if len(str(x))==3 | len(str(x))==4 else (-(eval(str(x))*20 +100)) for x in data_all['Shootings']]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    values_twoshoot = (-(eval(data_all.Shootings.str)*10 +100))
     
    data_all['Shootings_stats']= values_twoshoot.where(data_all.testlong ==3 | data_all.testlong==4)
    Merci d'avance pour votre aide !!!

  2. #2
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    qu'en est-il d'un résultat du type 0+3 0+2 (note l'espace) ? est-ce la même chose que 0+0+2+3 par exemple pour le calcul ?

    utiliser len() est plutôt cracra, et eval() c'est pire encore, on pourrait facilement envisager un truc du style re.split(r'[+ ]') pour récupérer les nombres et leur appliquer le traitement adéquat

    sinon pour ce qui est d'itérer sur la colonne tu peux utiliser .apply() en précisant comme second paramètre axis=1

  3. #3
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut
    salut merci pour ta réponse.

    Oui il faut rajouter un + (je l'avais mis au dessus dans mon code car dès fois il y a des bugs dans les données...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     data_all.Shootings= data_all.Shootings.str.replace(('^'),"")
    data_all.Shootings= data_all.Shootings.str.replace(('-'),"")
    data_all.Shootings= data_all.Shootings.str.replace(" ","+")
    Ok je vais regarder avec ta proposition, merci

  4. #4
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    si le but c'est juste de faire la somme des nombres, tu peux envisager une tournure de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    data_all['Shootings'].apply(lambda x: sum(map(int, re.findall(r'\d+', x))))
    (sans même avoir besoin de faire des replace() préalables)

  5. #5
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut
    Le but n'est pas que de déterminer la somme des nombres, je cherche à déterminer le pourcentage de réussite au tir en fonction de l'épreuve car parfois il y a deux tirs et d'autres fois il y en a 4.

    Donc lorsqu'il y seulement deux chiffres genre 1+3 cela fait 4 fautes donc une pourcentage de réussite de 60% (d’où ma formule dans le code Donc lorsqu'il y seulement deux chiffres genre 1+1+0+1 cela fait 3 fautes donc une pourcentage de réussite de 75% (d’où ma formule dans le code Et idéalement je souhaite que ces données soient dans une nouvelle colonne.

    J'ai testé ton code et j'obtiens une erreur de type, "expected string or bytes-like object"

    Je vais faire quelques essais avec tes propositions.

  6. #6
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut
    J'ai modifier le type en string mais la fonction ne semble pas fonctionner...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    data_all['Shootings_stats']= data_all['Shootings']
    data_all['Shootings_stats']=data_all['Shootings_stats'].astype('str')
    data_all['Shootings_stats'].apply(lambda x: sum(map(int, re.findall(r'\d+', x))))
    resultats:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        PursuitStartDistance     Result LegRank TeamRankAfterLeg  Shootings_stats  
    0                     0  1:29:02.8     NaN              NaN          0+5+1+8  
    1                     0      +11.7     2.0              2.0          0+1+0+2  
    2                     0       +8.6     1.0              2.0          0+1+0+0  
    3                     0  1:06:03.7     1.0              1.0          0+2+0+3  
    4                     0  1:29:02.8     5.0              1.0          0+1+1+3

  7. #7
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut
    En fait si ça fonctionne mais il faut faire ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    data_all['Shootings_stats']=data_all['Shootings_stats'].apply(lambda x: sum(map(int, re.findall(r'\d+', x))))

  8. #8
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut
    Alors je penses avoir trouvé la solution mais je ne sais pas si c'est très élégant, qu'en penses tu ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    def pourcentageReussite(x):
        if len(x)==3| len(x)==4:
            return -10*(sum(map(int, re.findall(r'\d+', x))))+100
        if len(x)==7:
            return -5*(sum(map(int, re.findall(r'\d+', x))))+100
     
     
    data_all['Shootings_stats']=data_all['Shootings_stats'].apply(pourcentageReussite)

    Merci beaucoup pour ton aide

  9. #9
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    tu peux peut-être tourner la fonction ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def pourcentageReussite(x):
        z = re.findall(r'\d+', x)  # len(z) vaut donc 2 ou 4
        return -2.5*len(z)*(sum(map(int, z)))+100
    l'essentiel étant que tu t'y retrouve et que ça fonctionne

  10. #10
    Membre averti
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2020
    Messages : 15
    Par défaut
    C'est plus court mais cela ne fonctionnera pas car pour len=2 on doit obtenir la valeur 10 et pour len=4 on doit obtenir la valeur 5

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

Discussions similaires

  1. Supprimer une ligne d'un DataFrame sous condition
    Par alexcot13 dans le forum Général Python
    Réponses: 7
    Dernier message: 15/06/2018, 18h20
  2. Réponses: 2
    Dernier message: 18/03/2016, 17h09
  3. Réponses: 7
    Dernier message: 11/12/2007, 09h08
  4. [Access] création d'une colonne avec un numéro d'occurence
    Par J-Menezo dans le forum Langage SQL
    Réponses: 9
    Dernier message: 30/01/2007, 08h34
  5. Réponses: 15
    Dernier message: 05/09/2006, 09h53

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