Appliquer la fonction Python à une colonne pandas et appliquer la sortie à plusieurs colonnes

Aug 20 2020

Bonjour la communauté,

J'ai lu tellement de réponses et de blogs que je ne suis pas en mesure de comprendre quelle chose simple me manque !. J'utilise la fonction «conditions» pour définir toutes les conditions et l'appliquer à une colonne de dataframe. Et si la condition est satisfaite, il devrait créer / mettre à jour 2 nouvelles colonnes de dataframe 'cat' et 'subcat'.

Ce serait d'une grande aide si vous pouviez m'aider ici!

dict = {'remark':['NA','NA','Category1','Category2','Category3'],
        'desc':['Present','Present','NA','Present','NA']
} 

df = pd.DataFrame(dict) 

Dataframe ressemble à ceci:

          remark       desc
0         NA           Present      
1         NA           Present        
2         Category1    NA                   
3         Category2    Present                   
4         Category3    NA            

J'ai écrit une fonction pour définir les conditions comme ci-dessous:

def conditions(s):

    if (s == 'Category1'):
        x = 'insufficient'
        y = 'resolution'
    elif (s=='Category2):
        x= 'insufficient'
        y= 'information'
    elif (s=='Category3):
        x= 'Duplicate'
        y= 'ID repeated'
    else:
        x= 'NA'
        y= 'NA'
    
    return (x,y)

J'ai plusieurs idées pour exécuter la fonction ci-dessus sur la colonne dataframe mais pas de chance.

df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([conditions(df)[0],conditions(df)[1]]))

Mon dataframe attendu devrait ressembler à ceci:

          remark       desc        cat           subcat
0         NA           Present     NA            NA      
1         NA           Present     NA            NA
2         Category1    NA          insufficient  resolution         
3         Category2    Present     insufficient  information              
4         Category3    NA          Duplicate     ID repeated

Merci beaucoup.

Réponses

2 sammywemmy Aug 20 2020 at 04:10

Une façon de contourner ce problème consiste à comprendre une liste:

df[['cat', 'subcat']] = [("insufficient", "resolution")  if word == "Category1" else 
                         ("insufficient", "information") if word == "Category2" else
                         ("Duplicate", "ID repeated")    if word == "Category3" else 
                         ("NA", "NA")
                         for word in df.remark]

  remark      desc               cat         subcat
0   NA        Present          NA              NA
1   NA        Present          NA              NA
2   Category1   NA          insufficient    resolution
3   Category2   Present     insufficient    information
4   Category3   NA          Duplicate       ID repeated

La réponse de @ dm2 montre comment y parvenir avec votre fonction. Le premier apply(conditions)crée une série contenant des tuples, le second applycrée des colonnes individuelles, formant une trame de données que vous pouvez ensuite affecter à catet subcat.

La raison pour laquelle je suggère une compréhension de liste est que, lorsque vous avez affaire à des chaînes, et dans Pandas, travailler avec des chaînes via python vanilla est le plus souvent plus rapide. De plus, avec la compréhension de la liste, le traitement est effectué une fois, vous n'avez pas besoin d'appliquer la fonction de conditions, puis d'appeler pd.Series. Cela vous donne une vitesse plus rapide. Les tests affirmeront ou démystifieront cela.

2 dm2 Aug 20 2020 at 04:12

Vous pourriez faire:

 df[['cat','subcat']] = df['remark'].apply(conditions).apply(pd.Series)

Production:

  remark      desc               cat         subcat
0   NA        Present          NA              NA
1   NA        Present          NA              NA
2   Category1   NA          insufficient    resolution
3   Category2   Present     insufficient    information
4   Category3   NA          Duplicate       ID repeated

Edit: C'est peut-être le moyen le plus simple d'appliquer votre fonction que vous avez déjà, mais au cas où vous auriez un énorme DataFrame, pour un code plus rapide, consultez la réponse de @sammywemmy en utilisant la compréhension de liste.

1 Quentin Aug 20 2020 at 04:13

Vous dataframepassez le tout là où il vous suffit de passer la variable lambda ( x).

df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))

*sur les iterables peuvent unpackles faire ainsi vous n'avez pas besoin d'appeler la même fonction deux fois pour extraire la sortie. Peut-être que le compilateur résout cela mais je ne pense pas ...

RichieV Aug 20 2020 at 04:11

Vous pouvez utiliser series.replaceavec un dictionnaire de mappage

df['cat'] = df.remark.replace({'Category1': 'insufficient',
    'Category2': 'insufficient', 'Category3': 'Duplicate'})
df['subcat'] = df.remark.replace({'Category1': 'resolution',
    'Category2': 'information', 'Category3': 'ID repeated'})

print(df)
      remark     desc           cat       subcat
0         NA  Present            NA           NA
1         NA  Present            NA           NA
2  Category1       NA  insufficient   resolution
3  Category2  Present  insufficient  information
4  Category3       NA     Duplicate  ID repeated