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.