Applica la funzione Python a una colonna panda e applica l'output a più colonne
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
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 apply
crea singole colonne, formando un dataframe che puoi quindi assegnare a cat
e 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.
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.
Stai passando l'intero in dataframe
cui devi solo passare la variabile lambda ( x
).
df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))
*
su iterabili unpack
li possono quindi non è necessario chiamare la stessa funzione due volte per estrarre l'output. Forse il compilatore risolve questo problema ma non credo proprio ...
È possibile utilizzare series.replace
con 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