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.