Applicazione della funzione con più argomenti per creare una nuova colonna Panda


165

Voglio creare una nuova colonna in un pandasframe di dati applicando una funzione a due colonne esistenti. Seguendo questa risposta sono stato in grado di creare una nuova colonna quando ho solo bisogno di una colonna come argomento:

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)

Tuttavia, non riesco a capire come fare la stessa cosa quando la funzione richiede più argomenti. Ad esempio, come posso creare una nuova colonna passando la colonna A e la colonna B alla funzione seguente?

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

Risposte:


136

In alternativa, è possibile utilizzare la funzione sottostante intorpidita:

>>> 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

o vettorializzare la funzione arbitraria nel caso generale:

>>> 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
Grazie per la risposta! Sono curioso, è questa la soluzione più veloce?
MV23,

6
La versione vettoriale np.vectorize()è incredibilmente veloce. Grazie.
stackoverflowuser2010,

Questa è una soluzione utile Se la dimensione degli argomenti di input per la funzione xey non è uguale, viene visualizzato un errore. In tal caso, la soluzione @RomanPekar funziona senza problemi. Non ho confrontato le prestazioni.
Ehsan Sadr,

So che questa è una vecchia risposta, ma: ho un caso limite, in cui np.vectorizenon funziona. Il motivo è che una delle colonne è del tipo pandas._libs.tslibs.timestamps.Timestamp, che viene convertito nel tipo numpy.datetime64dalla vettorializzazione. I due tipi non sono intercambiabili, causando un cattivo funzionamento della funzione. Qualche suggerimento su questo? (A parte .applyquesto, apparentemente da evitare)
ElRudi,

Ottima soluzione! nel caso qualcuno si stia chiedendo che vettorializzare funzioni bene e velocissimo anche per le funzioni di confronto delle stringhe.
infiniteloop,

227

Puoi andare con l'esempio @greenAfrican, se è possibile riscrivere la tua funzione. Ma se non vuoi riscrivere la tua funzione, puoi inserirlo in una funzione anonima all'interno di apply, in questo modo:

>>> 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
Questo è un ottimo suggerimento e lascia i riferimenti di colonna vicino alla chiamata di applicazione (in realtà). Ho usato questo suggerimento e il suggerimento di uscita multi-colonna @toto_tico fornito per generare una funzione 3 colonne in, 4 colonne in uscita! Funziona alla grande!
RufusVS,

7
Wow, sembra che tu sia l'unico a non concentrarti sull'esempio minimale di OP ma a risolvere l'intero problema, grazie, esattamente quello di cui avevo bisogno! :)
Matt,

38

Questo risolve il problema:

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

Puoi anche fare:

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

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

10
Questa risposta risolve questo esempio di giocattolo e mi basterà riscrivere la mia funzione effettiva, ma non affronta come applicare una funzione precedentemente definita senza riscriverla nelle colonne di riferimento.
Michael,

23

Se devi creare più colonne contemporaneamente :

  1. Crea il frame di dati:

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

    def fab(row):                                                  
        return row['A'] * row['B'], row['A'] + row['B']
  3. Assegna le nuove colonne:

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

1
Mi chiedevo come avrei potuto generare più colonne con una sola applicazione! L'ho usato con la risposta di @Roman Pekar per generare una funzione 3 colonne in, 4 colonne in uscita! Funziona alla grande!
RufusVS,

15

Ancora una sintassi pulita in stile dict:

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

o,

df["new_column"] = df["A"] * df["B"]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.