Applica la funzione Python a una colonna panda e applica l'output a più colonne

Aug 20 2020

Salve Community,

Ho letto così tante risposte e blog ma non sono in grado di capire quale semplice cosa mi sto perdendo !. Sto usando la funzione 'condizioni' per definire tutte le condizioni e applicarla a una colonna di dataframe. E se la condizione è soddisfatta, dovrebbe creare / aggiornare 2 nuove colonne di dataframe "cat" e "subcat".

Sarebbe di grande aiuto se voi ragazzi poteste aiutarmi qui!

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

df = pd.DataFrame(dict) 

Dataframe ha un aspetto simile a questo:

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

Ho scritto una funzione per definire le condizioni come di seguito:

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)

Ho più idee per eseguire la funzione di cui sopra sulla colonna dataframe ma senza fortuna.

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

Il dataframe previsto dovrebbe essere simile a questo:

          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

Grazie molto.

Risposte

2 sammywemmy Aug 20 2020 at 04:10

Un modo per aggirare questo è con una comprensione dell'elenco:

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 risposta di @ dm2 mostra come ottenerlo con la tua funzione. Il primo apply(conditions)crea una serie contenente tuple, il secondo applycrea singole colonne, formando un dataframe che puoi quindi assegnare a cate subcat.

Il motivo per cui suggerisco una comprensione delle liste è perché, quando hai a che fare con le stringhe, e in Panda, lavorare con le stringhe tramite vanilla python è il più delle volte più veloce. Inoltre, con la comprensione dell'elenco l'elaborazione viene eseguita una volta, non è necessario applicare la funzione delle condizioni e quindi chiamare pd.Series. Questo ti dà una maggiore velocità. I test lo affermeranno o smentiranno.

2 dm2 Aug 20 2020 at 04:12

Potresti fare:

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

Produzione:

  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

Modifica: questo potrebbe essere il modo più semplice per applicare la funzione che hai già, ma nel caso in cui tu abbia un DataFrame enorme, per un codice più veloce controlla la risposta di @sammywemmy usando la comprensione dell'elenco.

1 Quentin Aug 20 2020 at 04:13

Stai passando l'intero in dataframecui devi solo passare la variabile lambda ( x).

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

*su iterabili unpackli possono quindi non è necessario chiamare la stessa funzione due volte per estrarre l'output. Forse il compilatore risolve questo problema ma non credo proprio ...

RichieV Aug 20 2020 at 04:11

È possibile utilizzare series.replacecon un dizionario di mappe

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