pandas crea una nuova colonna basata sui valori di altre colonne / applica una funzione di più colonne, in base alle righe

Voglio applicare la mia funzione personalizzata (usa una scala if-else) a queste sei colonne (ERI_Hispanic, ERI_AmerInd_AKNatv, ERI_Asian, ERI_Black_Afr.Amer, ERI_HI_PacIsl, ERI_White) in ogni riga del mio dataframe.

Ho provato diversi metodi da altre domande ma ancora non riesco a trovare la risposta giusta per il mio problema. La parte critica di questo è che se la persona è contata come ispanica non può essere contata come qualsiasi altra cosa. Anche se hanno un "1" in un'altra colonna di etnia sono ancora contati come ispanici e non come due o più razze. Allo stesso modo, se la somma di tutte le colonne ERI è maggiore di 1 sono contati come due o più razze e non possono essere contati come un'unica etnia (eccetto ispanici). Speriamo che questo abbia senso. Qualsiasi aiuto sarà molto apprezzato.

È quasi come fare un ciclo for attraverso ogni riga e se ogni record soddisfa un criterio viene aggiunto a una lista ed eliminato dall'originale.

Dal dataframe sottostante ho bisogno di calcolare una nuova colonna basata sulla seguente specifica in SQL:

========================= CRITERIA ===============================

IF [ERI_Hispanic] = 1 THEN RETURN “Hispanic”
ELSE IF SUM([ERI_AmerInd_AKNatv] + [ERI_Asian] + [ERI_Black_Afr.Amer] + [ERI_HI_PacIsl] + [ERI_White]) > 1 THEN RETURN “Two or More”
ELSE IF [ERI_AmerInd_AKNatv] = 1 THEN RETURN “A/I AK Native”
ELSE IF [ERI_Asian] = 1 THEN RETURN “Asian”
ELSE IF [ERI_Black_Afr.Amer] = 1 THEN RETURN “Black/AA”
ELSE IF [ERI_HI_PacIsl] = 1 THEN RETURN “Haw/Pac Isl.”
ELSE IF [ERI_White] = 1 THEN RETURN “White”

Commento: Se il flag ERI per l'ispanico è vero (1), il dipendente è classificato come "ispanico".

Commento: Se più di 1 flag ERI non ispanico è vero, restituire "Due o più"

====================== DATAFRAME ===========================

     lname          fname       rno_cd  eri_afr_amer    eri_asian   eri_hawaiian    eri_hispanic    eri_nat_amer    eri_white   rno_defined
0    MOST           JEFF        E       0               0           0               0               0               1           White
1    CRUISE         TOM         E       0               0           0               1               0               0           White
2    DEPP           JOHNNY              0               0           0               0               0               1           Unknown
3    DICAP          LEO                 0               0           0               0               0               1           Unknown
4    BRANDO         MARLON      E       0               0           0               0               0               0           White
5    HANKS          TOM         0                       0           0               0               0               1           Unknown
6    DENIRO         ROBERT      E       0               1           0               0               0               1           White
7    PACINO         AL          E       0               0           0               0               0               1           White
8    WILLIAMS       ROBIN       E       0               0           1               0               0               0           White
9    EASTWOOD       CLINT       E       0               0           0               0               0               1           White
Soluzione

OK, due passi per questo - il primo è scrivere una funzione che faccia la traduzione che vuoi - ho messo insieme un esempio basato sul tuo pseudo-codice:

def label_race (row):
   if row['eri_hispanic'] == 1 :
      return 'Hispanic'
   if row['eri_afr_amer'] + row['eri_asian'] + row['eri_hawaiian'] + row['eri_nat_amer'] + row['eri_white'] > 1 :
      return 'Two Or More'
   if row['eri_nat_amer'] == 1 :
      return 'A/I AK Native'
   if row['eri_asian'] == 1:
      return 'Asian'
   if row['eri_afr_amer']  == 1:
      return 'Black/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Pac Isl.'
   if row['eri_white'] == 1:
      return 'White'
   return 'Other'

Potresti voler rivedere questo, ma sembra fare il trucco - nota che il parametro che va nella funzione è considerato un oggetto Serie etichettato "row".

Successivamente, usate la funzione apply in pandas per applicare la funzione - ad esempio

df.apply (lambda row: label_race(row), axis=1)

Notate lo specificatore axis=1, che significa che l'applicazione viene fatta a livello di riga, piuttosto che di colonna. I risultati sono qui:

0           White
1        Hispanic
2           White
3           White
4           Other
5           White
6     Two Or More
7           White
8    Haw/Pac Isl.
9           White

Se siete soddisfatti di questi risultati, eseguitelo di nuovo, salvando i risultati in una nuova colonna del vostro dataframe originale.

df['race_label'] = df.apply (lambda row: label_race(row), axis=1)

Il dataframe risultante assomiglia a questo (scorri a destra per vedere la nuova colonna):

      lname   fname rno_cd  eri_afr_amer  eri_asian  eri_hawaiian   eri_hispanic  eri_nat_amer  eri_white rno_defined    race_label
0      MOST    JEFF      E             0          0             0              0             0          1       White         White
1    CRUISE     TOM      E             0          0             0              1             0          0       White      Hispanic
2      DEPP  JOHNNY    NaN             0          0             0              0             0          1     Unknown         White
3     DICAP     LEO    NaN             0          0             0              0             0          1     Unknown         White
4    BRANDO  MARLON      E             0          0             0              0             0          0       White         Other
5     HANKS     TOM    NaN             0          0             0              0             0          1     Unknown         White
6    DENIRO  ROBERT      E             0          1             0              0             0          1       White   Two Or More
7    PACINO      AL      E             0          0             0              0             0          1       White         White
8  WILLIAMS   ROBIN      E             0          0             1              0             0          0       White  Haw/Pac Isl.
9  EASTWOOD   CLINT      E             0          0             0              0             0          1       White         White
Commentari (5)

Poiché questo è il primo risultato di Google per 'pandas new column from others', ecco un semplice esempio:

import pandas as pd

# make a simple dataframe
df = pd.DataFrame({'a':[1,2], 'b':[3,4]})
df
#    a  b
# 0  1  3
# 1  2  4

# create an unattached column with an index
df.apply(lambda row: row.a + row.b, axis=1)
# 0    4
# 1    6

# do same but attach it to the dataframe
df['c'] = df.apply(lambda row: row.a + row.b, axis=1)
df
#    a  b  c
# 0  1  3  4
# 1  2  4  6

Se ottenete il SettingWithCopyWarning potete farlo anche in questo modo:

fn = lambda row: row.a + row.b # define a function for the new column
col = df.apply(fn, axis=1) # get column data with an index
df = df.assign(c=col.values) # assign values to column 'c'

Fonte: https://stackoverflow.com/a/12555510/243392

E se il vostro nome di colonna include spazi potete usare una sintassi come questa:

df = df.assign(**{'some column name': col.values})

Ed ecco la documentazione per apply, e assign.

Commentari (4)

.apply() prende una funzione come primo parametro; passate la funzione label_race come tale:

df['race_label'] = df.apply(label_race, axis=1)

Non c'è bisogno di fare una funzione lambda per passare una funzione.

Commentari (0)