Panda: come posso usare la funzione apply () per una singola colonna?


260

Ho un frame di dati Panda con due colonne. Devo modificare i valori della prima colonna senza influire sulla seconda e ripristinare l'intero frame di dati con i valori della prima colonna modificati. Come posso farlo usando apply in panda?


4
Si prega di inviare alcuni dati di esempio di input e output desiderato.
Fabio Lamanna,

Non dovresti quasi mai usare applyin una situazione come questa. Operare invece direttamente sulla colonna.
Ted Petrou,

Come ha detto Ted Petrou, evitare di usare applyil più possibile. Se non sei sicuro di doverlo usare, probabilmente non lo fai. Consiglio di dare un'occhiata a Quando dovrei mai voler usare Panda Applica () nel mio codice? .
cs95,

La domanda non è completamente chiara: si applica una funzione a tutti gli elementi di una colonna o si applica una funzione all'intera colonna (ad esempio: invertire la colonna)?
Pierre ALBARÈDE,

Risposte:


339

Dato un esempio di frame di dati dfcome:

a,b
1,2
2,3
3,4
4,5

quello che vuoi è:

df['a'] = df['a'].apply(lambda x: x + 1)

che ritorna:

   a  b
0  2  2
1  3  3
2  4  4
3  5  5

9
applynon dovrebbe mai essere usato in una situazione come questa
Ted Petrou,

5
@TedPetrou hai perfettamente ragione, era solo un esempio di come applicare una funzione generale su una singola colonna, come ha chiesto l'OP.
Fabio Lamanna,

14
Quando provo a fare questo, ricevo il seguente avviso: "Un valore sta cercando di essere impostato su una copia di una porzione da un DataFrame. Prova a usare .loc [row_indexer, col_indexer] = value invece"
dagrun

24
Per curiosità: perché non applicare la domanda in quella situazione? Qual è esattamente la situazione?
Zio Ben Ben,

19
@UncleBenBen in generale applyusa un loop interno su righe che è molto più lento delle funzioni vettorializzate, come ad esempio df.a = df.a / 2(vedi risposta Mike Muller).
Fabio Lamanna,

66

Per una singola colonna meglio usare map(), in questo modo:

df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9



df['a'] = df['a'].map(lambda a: a / 2.)

      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

78
Perché è map()meglio che apply()per una singola colonna?
ChaimG,

2
Questo è stato molto utile. L'ho usato per estrarre i nomi dei file dai percorsi memorizzati in una colonnadf['file_name'] = df['Path'].map(lambda a: os.path.basename(a))
mmann1123

46
map () è per Series (ovvero singole colonne) e funziona su una cella alla volta, mentre apply () è per DataFrame e funziona su un'intera riga alla volta.
jpcgt,

3
@jpcgt Significa che la mappa è più veloce di quella applicabile in questo caso?
Viragos,

@ChaimG vedo che questo sistema operativo spiega bene: stackoverflow.com/a/19798528/571828
象 嘉 道

41

Non hai bisogno di alcuna funzione. Puoi lavorare direttamente su un'intera colonna.

Dati di esempio:

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

Metà di tutti i valori nella colonna a:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

E se volessi dividere ogni elemento in una colonna per "/" e prendere la prima parte?
K47,

12

Sebbene le risposte fornite siano corrette, modificano il frame di dati iniziale, il che non è sempre desiderabile (e, dato l'OP ha chiesto esempi di "utilizzo apply", potrebbe essere che volessero una versione che restituisca un nuovo frame di dati, come applyfa).

Questo è possibile utilizzando assign: è valido per assignle colonne esistenti, come afferma la documentazione (l'enfasi è mia):

Assegna nuove colonne a un DataFrame.

Restituisce un nuovo oggetto con tutte le colonne originali oltre a quelle nuove. Le colonne esistenti che vengono riassegnate verranno sovrascritte .

In breve:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

In [3]: df.assign(a=lambda df: df.a / 2)
Out[3]: 
      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

In [4]: df
Out[4]: 
    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9

Nota che alla funzione verrà passato l'intero frame di dati, non solo la colonna che desideri modificare, quindi dovrai assicurarti di selezionare la colonna giusta nel tuo lambda.


9

Se sei davvero preoccupato per la velocità di esecuzione della tua funzione apply e hai un enorme set di dati su cui lavorare, potresti usare swifter per eseguire un'esecuzione più veloce, ecco un esempio per swifter su dataframe panda:

import pandas as pd
import swifter

def fnc(m):
    return m*3+4

df = pd.DataFrame({"m": [1,2,3,4,5,6], "c": [1,1,1,1,1,1], "x":[5,3,6,2,6,1]})

# apply a self created function to a single column in pandas
df["y"] = df.m.swifter.apply(fnc)

Ciò consentirà a tutti i core della CPU di calcolare il risultato, quindi sarà molto più veloce delle normali funzioni di applicazione. Prova e fammi sapere se ti sarà utile.


1

Vorrei provare un calcolo complesso usando datetime e considerando null o spazi vuoti. Sto riducendo 30 anni in una colonna datetime e usando il applymetodo lambdae convertendo il formato datetime. La linea if x != '' else xsi occuperà di conseguenza di tutti gli spazi vuoti o null.

df['Date'] = df['Date'].fillna('')
df['Date'] = df['Date'].apply(lambda x : ((datetime.datetime.strptime(str(x), '%m/%d/%Y') - datetime.timedelta(days=30*365)).strftime('%Y%m%d')) if x != '' else x)
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.