Anwenden einer Funktion mit mehreren Argumenten zum Erstellen einer neuen Pandas-Spalte


165

Ich möchte eine neue Spalte in einem pandasDatenrahmen erstellen, indem ich eine Funktion auf zwei vorhandene Spalten anwende. Nach dieser Antwort konnte ich eine neue Spalte erstellen, wenn ich nur eine Spalte als Argument benötige:

import pandas as pd
df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})

def fx(x):
    return x * x

print(df)
df['newcolumn'] = df.A.apply(fx)
print(df)

Ich kann jedoch nicht herausfinden, wie ich dasselbe tun soll, wenn die Funktion mehrere Argumente erfordert. Wie erstelle ich beispielsweise eine neue Spalte, indem ich Spalte A und Spalte B an die folgende Funktion übergebe?

def fxy(x, y):
    return x * y

Antworten:


136

Alternativ können Sie die zugrunde liegende Funktion numpy verwenden:

>>> import numpy as np
>>> df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
>>> df['new_column'] = np.multiply(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300

oder beliebige Funktion im allgemeinen Fall vektorisieren:

>>> def fx(x, y):
...     return x*y
...
>>> df['new_column'] = np.vectorize(fx)(df['A'], df['B'])
>>> df
    A   B  new_column
0  10  20         200
1  20  30         600
2  30  10         300

2
Danke für die Antwort! Ich bin neugierig, ist das die schnellste Lösung?
MV23

6
Die vektorisierte Version mit np.vectorize()ist erstaunlich schnell. Danke dir.
stackoverflowuser2010

Dies ist eine nützliche Lösung. Wenn die Größe der Eingabeargumente für die Funktion x und y nicht gleich ist, wird eine Fehlermeldung angezeigt. In diesem Fall funktioniert die @ RomanPekar-Lösung problemlos. Ich habe die Leistung nicht verglichen.
Ehsan Sadr

Ich weiß, dass dies eine alte Antwort ist, aber: Ich habe einen Randfall, in dem np.vectorizees nicht funktioniert. Der Grund ist, dass eine der Spalten vom Typ ist pandas._libs.tslibs.timestamps.Timestamp, der numpy.datetime64durch die Vektorisierung in den Typ umgewandelt wird. Die beiden Typen sind nicht austauschbar, wodurch sich die Funktion schlecht verhält. Irgendwelche Vorschläge dazu? (Anders als .applydies anscheinend zu vermeiden ist)
ElRudi

Tolle Lösung! falls sich jemand wundert, funktioniert vectorize auch für String-Vergleichsfunktionen gut und superschnell.
Infiniteloop

226

Sie können mit dem Beispiel @greenAfrican fortfahren, wenn Sie Ihre Funktion neu schreiben können. Wenn Sie Ihre Funktion jedoch nicht neu schreiben möchten, können Sie sie wie folgt in eine anonyme Funktion in apply einbinden:

>>> def fxy(x, y):
...     return x * y

>>> df['newcolumn'] = df.apply(lambda x: fxy(x['A'], x['B']), axis=1)
>>> df
    A   B  newcolumn
0  10  20        200
1  20  30        600
2  30  10        300

4
Dies ist ein großartiger Tipp, und die Spaltenreferenzen bleiben in der Nähe des Apply-Aufrufs (tatsächlich darin). Ich habe diesen Tipp und den mehrspaltigen Ausgabetipp @toto_tico verwendet, um eine 3-Spalten-In- und 4-Spalten-Out-Funktion zu generieren! Funktioniert super!
RufusVS

7
Wow, es scheint, dass Sie der einzige sind, der sich nicht auf das minimale Beispiel von OP konzentriert, sondern das ganze Problem anspricht, danke, genau das, was ich brauchte! :)
Matt

38

Dies löst das Problem:

df['newcolumn'] = df.A * df.B

Sie könnten auch tun:

def fab(row):
  return row['A'] * row['B']

df['newcolumn'] = df.apply(fab, axis=1)

10
Diese Antwort löst dieses Spielzeugbeispiel und reicht aus, um meine eigentliche Funktion neu zu schreiben. Sie behandelt jedoch nicht, wie eine zuvor definierte Funktion angewendet wird, ohne sie in Referenzspalten umzuschreiben.
Michael

23

Wenn Sie mehrere Spalten gleichzeitig erstellen müssen :

  1. Erstellen Sie den Datenrahmen:

    import pandas as pd
    df = pd.DataFrame({"A": [10,20,30], "B": [20, 30, 10]})
  2. Erstellen Sie die Funktion:

    def fab(row):                                                  
        return row['A'] * row['B'], row['A'] + row['B']
  3. Weisen Sie die neuen Spalten zu:

    df['newcolumn'], df['newcolumn2'] = zip(*df.apply(fab, axis=1))

1
Ich habe mich gefragt, wie ich mit einer Bewerbung mehrere Spalten generieren kann! Ich habe dies mit der Antwort von @Roman Pekar verwendet, um eine 3-Spalten-In- und 4-Spalten-Out-Funktion zu generieren! Funktioniert super!
RufusVS

14

Noch eine saubere Syntax im Diktatstil:

df["new_column"] = df.apply(lambda x: x["A"] * x["B"], axis = 1)

oder,

df["new_column"] = df["A"] * df["B"]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.