636 Stimmen

Erstellen Sie eine neue Spalte basierend auf Werten aus anderen Spalten / wenden Sie eine Funktion auf mehrere Spalten in Pandas zeilenweise an

Ich möchte meine benutzerdefinierte Funktion (die eine if-else-Leiter verwendet) auf diese sechs Spalten (ERI_Hispanic, ERI_AmerInd_AKNatv, ERI_Asian, ERI_Black_Afr.Amer, ERI_HI_PacIsl, ERI_White) in jeder Zeile meines Dataframes anwenden.

Ich habe verschiedene Methoden aus anderen Fragen ausprobiert, aber finde immer noch keine richtige Lösung für mein Problem. Der entscheidende Punkt dabei ist, dass wenn die Person als Hispanic gezählt wird, sie nicht als etwas anderes gezählt werden kann. Selbst wenn sie eine "1" in einer anderen Ethnizitätsspalte haben, werden sie immer noch als Hispanic und nicht als zwei oder mehr Rassen gezählt. Ebenso, wenn die Summe aller ERI-Spalten größer als 1 ist, werden sie als zwei oder mehr Rassen gezählt und können nicht als eine eindeutige Ethnizität gezählt werden (außer Hispanic).

Es ist fast so, als würde man eine for-Schleife durch jede Zeile machen und wenn jeder Datensatz ein Kriterium erfüllt, werden sie einer Liste hinzugefügt und aus dem Original entfernt.

Aus dem unten stehenden Dataframe muss ich eine neue Spalte gemäß der folgenden Spezifikation in SQL berechnen:

KRITERIEN

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”

Kommentar: Wenn das ERI-Flag für Hispanic True (1) ist, wird der Mitarbeiter als “Hispanic” eingestuft

Kommentar: Wenn mehr als 1 nicht-hispanisches ERI-Flag True ist, wird “Two or More” zurückgegeben

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

779voto

Thomas Kimber Punkte 9353

OK, zwei Schritte dazu - zuerst müssen Sie eine Funktion schreiben, die die gewünschte Übersetzung durchführt - ich habe ein Beispiel basierend auf Ihrem Pseudocode zusammengestellt:

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 'Zwei oder mehr'
   if row['eri_nat_amer'] == 1:
      return 'A/I AK Native'
   if row['eri_asian'] == 1:
      return 'Asiatisch'
   if row['eri_afr_amer'] == 1:
      return 'Schwarz/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Pac Isl.'
   if row['eri_white'] == 1:
      return 'Weiß'
   return 'Andere'

Sie möchten vielleicht überprüfen, aber es scheint zu funktionieren - beachten Sie, dass der Parameter, der in die Funktion übergeben wird, als ein Series-Objekt mit der Bezeichnung "row" betrachtet wird.

Verwenden Sie als nächstes die apply-Funktion in Pandas, um die Funktion anzuwenden - z.B.

df.apply(label_race, axis=1)

Beachten Sie den axis=1 Parameter. Das bedeutet, dass die Anwendung auf Zeilenebene und nicht auf Spaltenebene erfolgt. Die Ergebnisse sind hier:

0           Weiß
1        Hispanic
2           Weiß
3           Weiß
4           Andere
5           Weiß
6     Zwei oder mehr
7           Weiß
8    Haw/Pac Isl.
9           Weiß

Wenn Sie mit diesen Ergebnissen zufrieden sind, führen Sie es erneut aus und speichern Sie die Ergebnisse in einer neuen Spalte in Ihrem Original-Datenrahmen.

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

Der resultierende Datenrahmen sieht so aus (scrollen Sie nach rechts, um die neue Spalte zu sehen):

      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       Weiß         Weiß
1    CRUISE     TOM      E             0          0             0              1             0          0       Weiß      Hispanic
2      DEPP  JOHNNY    NaN             0          0             0              0             0          1     Unknown         Weiß
3     DICAP     LEO    NaN             0          0             0              0             0          1     Unknown         Weiß
4    BRANDO  MARLON      E             0          0             0              0             0          0       Weiß         Andere
5     HANKS     TOM    NaN             0          0             0              0             0          1     Unknown         Weiß
6    DENIRO  ROBERT      E             0          1             0              0             0          1       Weiß   Zwei oder mehr
7    PACINO      AL      E             0          0             0              0             0          1       Weiß         Weiß
8  WILLIAMS   ROBIN      E             0          0             1              0             0          0       Weiß  Haw/Pac Isl.
9  EASTWOOD   CLINT      E             0          0             0              0             0          1       Weiß         Weiß

445voto

Brian Burns Punkte 17530

Da dies das erste Google-Ergebnis für 'Pandas neue Spalte aus anderen' ist, hier ein einfaches Beispiel:

import pandas as pd

# ein einfaches DataFrame erstellen
df = pd.DataFrame({'a':[1,2], 'b':[3,4]})
df
#    a  b
# 0  1  3
# 1  2  4

# eine unverbundene Spalte mit einem Index erstellen
df.apply(lambda row: row.a + row.b, axis=1)
# 0    4
# 1    6

# dasselbe tun, aber es am DataFrame anfügen
df['c'] = df.apply(lambda row: row.a + row.b, axis=1)
df
#    a  b  c
# 0  1  3  4
# 1  2  4  6

Wenn Sie die SettingWithCopyWarning erhalten, können Sie es auch auf diese Weise tun:

col = df.apply(lambda row: row.a + row.b, axis=1)
df = df.assign(c=col.values) # Werte der Spalte 'c' zuweisen

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

Und wenn Ihr Spaltenname Leerzeichen enthält, können Sie eine Syntax wie diese verwenden:

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

Und hier ist die Dokumentation für apply und assign.

143voto

user3483203 Punkte 48933

Die oben genannten Antworten sind vollkommen gültig, aber es existiert eine vektorisierte Lösung in Form von numpy.select. Dies ermöglicht es Ihnen, Bedingungen zu definieren und dann Ausgaben für diese Bedingungen effizienter zu definieren als bei der Verwendung von apply:


Definieren Sie zunächst die Bedingungen:

conditions = [
    df['eri_hispanic'] == 1,
    df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
    df['eri_nat_amer'] == 1,
    df['eri_asian'] == 1,
    df['eri_afr_amer'] == 1,
    df['eri_hawaiian'] == 1,
    df['eri_white'] == 1,
]

Definieren Sie nun die entsprechenden Ausgaben:

outputs = [
    'Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White'
]

Verwenden Sie schließlich numpy.select:

res = np.select(conditions, outputs, 'Other')
pd.Series(res)

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

Warum sollte numpy.select anstelle von apply verwendet werden? Hier sind einige Leistungsüberprüfungen:

df = pd.concat([df]*1000)

In [42]: %timeit df.apply(lambda row: label_race(row), axis=1)
1.07 s ± 4.16 ms pro Schleife (Mittelwert ± Standardabweichung von 7 Schleifen, 1 Schleife pro Schleife)

In [44]: %%timeit
    ...: conditions = [
    ...:     df['eri_hispanic'] == 1,
    ...:     df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
    ...:     df['eri_nat_amer'] == 1,
    ...:     df['eri_asian'] == 1,
    ...:     df['eri_afr_amer'] == 1,
    ...:     df['eri_hawaiian'] == 1,
    ...:     df['eri_white'] == 1,
    ...: ]
    ...:
    ...: outputs = [
    ...:     'Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White'
    ...: ]
    ...:
    ...: np.select(conditions, outputs, 'Other')
    ...:
    ...:
3.09 ms ± 17 µs pro Schleife (Mittelwert ± Standardabweichung von 7 Schleifen, 100 Schleifen pro Schleife)

Die Verwendung von numpy.select führt zu einer erheblich verbesserten Leistung, und der Unterschied wird nur größer, wenn die Datenmenge wächst.

43voto

.apply() nimmt als ersten Parameter eine Funktion entgegen; übergeben Sie die Funktion label_race wie folgt:

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

Sie müssen keine Lambda-Funktion erstellen, um eine Funktion zu übergeben.

35voto

Mohamed Thasin ah Punkte 9368

Versuche dies,

df.loc[df['eri_white']==1,'race_label'] = 'Weiß'
df.loc[df['eri_hawaiian']==1,'race_label'] = 'Haw/Paz Insulaner'
df.loc[df['eri_afr_amer']==1,'race_label'] = 'Schwarze/AA'
df.loc[df['eri_asian']==1,'race_label'] = 'Asiatisch'
df.loc[df['eri_nat_amer']==1,'race_label'] = 'A/I AK Ureinwohner'
df.loc[(df['eri_afr_amer'] + df['eri_asian'] + df['eri_hawaiian'] + df['eri_nat_amer'] + df['eri_white']) > 1,'race_label'] = 'Zwei Oder Mehr'
df.loc[df['eri_hispanic']==1,'race_label'] = 'Hispanisch'
df['race_label'].fillna('Andere', inplace=True)

Ausgabe:

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

   eri_hispanic  eri_nat_amer  eri_white rno_defined    race_label  
0             0             0          1       Weiß             Weiß  
1             1             0          0       Weiß        Hispanisch  
2             0             0          1     Unknown             Weiß  
3             0             0          1     Unknown             Weiß  
4             0             0          0       Weiß            Andere  
5             0             0          1     Unknown             Weiß  
6             0             0          1       Weiß  Zwei Oder Mehr  
7             0             0          1       Weiß             Weiß  
8             0             0          0       Weiß  Haw/Paz Insulaner  
9             0             0          1       Weiß             Weiß 

Verwenden Sie .loc anstelle von apply.

es verbessert die Vektorisierung.

.loc funktioniert auf einfache Weise, maskiert Zeilen basierend auf der Bedingung, wendet Werte auf die eingefrorenen Zeilen an.

für weitere Details besuchen Sie .loc docs

Leistungsmetriken:

Akzeptierte Antwort:

def label_race (row):
   if row['eri_hispanic'] == 1 :
      return 'Hispanisch'
   if row['eri_afr_amer'] + row['eri_asian'] + row['eri_hawaiian'] + row['eri_nat_amer'] + row['eri_white'] > 1 :
      return 'Zwei Oder Mehr'
   if row['eri_nat_amer'] == 1 :
      return 'A/I AK Ureinwohner'
   if row['eri_asian'] == 1:
      return 'Asiatisch'
   if row['eri_afr_amer']  == 1:
      return 'Schwarze/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Paz Insulaner'
   if row['eri_white'] == 1:
      return 'Weiß'
   return 'Andere'

df=pd.read_csv('dataser.csv')
df = pd.concat([df]*1000)

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

1.15 s ± 46,5 ms pro Schleife (Mittelwert ± Standardabweichung von 7 Durchläufen, 1 Schleife pro Durchlauf)

Mein vorgeschlagene Antwort:

def label_race(df):
    df.loc[df['eri_white']==1,'race_label'] = 'Weiß'
    df.loc[df['eri_hawaiian']==1,'race_label'] = 'Haw/Paz Insulaner'
    df.loc[df['eri_afr_amer']==1,'race_label'] = 'Schwarze/AA'
    df.loc[df['eri_asian']==1,'race_label'] = 'Asiatisch'
    df.loc[df['eri_nat_amer']==1,'race_label'] = 'A/I AK Ureinwohner'
    df.loc[(df['eri_afr_amer'] + df['eri_asian'] + df['eri_hawaiian'] + df['eri_nat_amer'] + df['eri_white']) > 1,'race_label'] = 'Zwei Oder Mehr'
    df.loc[df['eri_hispanic']==1,'race_label'] = 'Hispanisch'
    df['race_label'].fillna('Andere', inplace=True)
df=pd.read_csv('s22.csv')
df = pd.concat([df]*1000)

%timeit label_race(df)

24,7 ms ± 1,7 ms pro Schleife (Mittelwert ± Standardabweichung von 7 Durchläufen, 10 Schleifen pro Durchlauf)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X