Erstellen einer neuen Spalte basierend auf der if-elif-else-Bedingung

100

Ich habe einen DataFrame df:

    A    B
a   2    2 
b   3    1
c   1    3

Ich möchte eine neue Spalte basierend auf den folgenden Kriterien erstellen:

wenn Reihe A == B: 0

wenn ReiheA > B: 1

wenn Reihe A < B: -1

In Anbetracht der obigen Tabelle sollte es also sein:

    A    B    C
a   2    2    0
b   3    1    1
c   1    3   -1 

Bieten Pandas in typischen if elseFällen np.where(df.A > df.B, 1, -1)eine spezielle Syntax, um mein Problem mit einem Schritt zu lösen (ohne dass drei neue Spalten erstellt und dann das Ergebnis kombiniert werden müssen)?

Nutship
quelle
Sie könnten einfach eine Funktion definieren und diese an übergeben applyund setzen axis=1würde funktionieren, nicht sicher, ob ich mir eine Operation
vorstellen
Ihre Lösung besteht darin, 3 Spalten zu erstellen und zu einer Spalte zu kombinieren, oder haben Sie etwas anderes im Sinn?
Nutship
Sie sagen immer wieder "3 Spalten erstellen", aber ich bin mir nicht sicher, worauf Sie sich beziehen.
DSM
1
@DSM hat diese Frage beantwortet, aber ich meinte so etwas wie df['C']=df.apply(myFunc(row), axis=1)wo myFunc macht was Sie wollen, dies beinhaltet nicht das Erstellen von '3 Spalten'
EdChum

Antworten:

146

Um einige der oben beschriebenen Ansätze zu formalisieren:

Erstellen Sie eine Funktion, die die Zeilen Ihres Datenrahmens wie folgt bearbeitet:

def f(row):
    if row['A'] == row['B']:
        val = 0
    elif row['A'] > row['B']:
        val = 1
    else:
        val = -1
    return val

Wenden Sie es dann auf Ihren Datenrahmen an, indem Sie die folgende axis=1Option übergeben:

In [1]: df['C'] = df.apply(f, axis=1)

In [2]: df
Out[2]:
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1

Dies ist natürlich nicht vektorisiert, sodass die Leistung bei Skalierung auf eine große Anzahl von Datensätzen möglicherweise nicht so gut ist. Trotzdem denke ich, dass es viel besser lesbar ist. Besonders aus einem SAS-Hintergrund.

Zelazny7
quelle
1
Vielen Dank, ich
beginne
4
Was ist, wenn ich einen anderen Parameter zusammen mit der Zeile in der Funktion übergeben möchte? Wenn ich das tue, heißt es Zeile nicht definiert ..
Prashanth Manohar
3
Sie müssen den argsParameter der .applyFunktion verwenden: pandas.pydata.org/pandas-docs/stable/generated/…
Zelazny7
1
Ich bin ein alter SAS-Benutzer, der Python lernt, und es gibt definitiv eine Lernkurve! :-) Zum Beispiel könnte der obige Code in SAS wie folgt geschrieben werden: data df; set df; if A=B then C=0; else if A>B then C=1; else C=-1; run;Sehr elegant und einfach.
RobertF
1
Eine gut definierte Antwort
Sahil Nagpal
51
df.loc[df['A'] == df['B'], 'C'] = 0
df.loc[df['A'] > df['B'], 'C'] = 1
df.loc[df['A'] < df['B'], 'C'] = -1

Einfach durch Indizieren zu lösen. Die erste Codezeile lautet wie Afolgt : Wenn die Spalte der Spalte entspricht, Berstellen Sie die Spalte und setzen Sie sie Cauf 0.

Brian
quelle
17

Für diese spezielle Beziehung können Sie Folgendes verwenden np.sign:

>>> df["C"] = np.sign(df.A - df.B)
>>> df
   A  B  C
a  2  2  0
b  3  1  1
c  1  3 -1
DSM
quelle
6

Geben Sie hier die Bildbeschreibung ein

Nehmen wir an, oben ist Ihr ursprünglicher Datenrahmen und Sie möchten eine neue Spalte 'alt' hinzufügen.

Wenn das Alter größer als 50 Jahre ist, betrachten wir es als älter = ja, andernfalls als falsch

Schritt 1: Abrufen der Indizes von Zeilen mit einem Alter von mehr als 50 Jahren

row_indexes=df[df['age']>=50].index

Schritt 2: Mit .loc können wir der Spalte einen neuen Wert zuweisen

df.loc[row_indexes,'elderly']="yes"

Gleiches gilt für Kinder unter 50 Jahren

row_indexes=df[df['age']<50].index

df[row_indexes,'elderly']="no"

Ravi G.
quelle