2012-12-03 7 views
61

Sto cercando un modo efficace per rimuovere le parti indesiderate dalle stringhe in una colonna DataFrame.Pandas DataFrame: rimuove le parti indesiderate dalle stringhe in una colonna

dati assomiglia:

time result 
1 09:00 +52A 
2 10:00 +62B 
3 11:00 +44a 
4 12:00 +30b 
5 13:00 -110a 

ho bisogno di tagliare questi dati per:

time result 
1 09:00 52 
2 10:00 62 
3 11:00 44 
4 12:00 30 
5 13:00 110 

ho provato .str.lstrip('+-') e. str.rstrip('aAbBcC'), ma ha ottenuto un errore:

TypeError: wrapper() takes exactly 1 argument (2 given) 

Qualsiasi puntatori sarebbe molto apprezzato!

+0

C'è un modo molto semplice per farlo utilizzando il metodo 'extract'. Vedi [questa risposta sotto] (https://stackoverflow.com/a/47107237/3707607). –

risposta

79
data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC')) 
+0

thx! che funzioni. Sto ancora confezionamento mia mente intorno map(), non è sicuro quando usare o non usare lo ... –

+0

mi ha fatto piacere vedere che questo metodo funziona anche con la funzione di sostituzione. – BKay

+0

@eumiro come si applica questo risultato se l'iterazione ogni colonna? – medev21

12

C'è un bug qui: attualmente non possono passare gli argomenti al str.lstrip e str.rstrip:

http://github.com/pydata/pandas/issues/2411

EDIT: 2012/12/07 questo funziona ora sul ramo dev:

In [8]: df['result'].str.lstrip('+-').str.rstrip('aAbBcC') 
Out[8]: 
1  52 
2  62 
3  44 
4  30 
5 110 
Name: result 
+0

Sembra funzionare per me, mi manca qui? –

18

Nel caso particolare in cui si conosce il numero di posizioni che si desidera rimuovere dalla colonna dataframe, è possibile uso stringa indicizzazione all'interno di una funzione lambda per sbarazzarsi di che le parti:

ultimo carattere:

data['result'] = data['result'].map(lambda x: str(x)[:-1]) 

primi due caratteri:

data['result'] = data['result'].map(lambda x: str(x)[2:]) 
+0

Ho bisogno di tagliare le coordinate geografiche a 8 caratteri (compresi (.), (-)) e nel caso in cui siano meno di 8 ho bisogno di inserire '0' alla fine per rendere tutte le coordinate 8 caratteri. Qual è il modo più semplice per farlo? –

+0

Non capisco perfettamente il tuo problema, ma potresti aver bisogno di cambiare la funzione lambda in qualcosa come "{0: .8f}". Format (x) – MonkeyButter

+0

Grazie mille per la risposta. In parole semplici ho dataframe con coordinate geografiche - latitudine e longitudine come due colonne. La lunghezza dei caratteri è più di 8 caratteri e io mantengo solo 8 caratteri a partire dal primo che dovrebbero includere anche (-) e (.). –

29

userei i panda funzione di sostituzione, molto semplice e potente come puoi usare regex. Sotto sto usando l'espressione regolare \ D per rimuovere eventuali caratteri non numerici, ma, ovviamente, si potrebbe ottenere molto creativo con espressioni regolari.

data['result'].replace(regex=True,inplace=True,to_replace=r'\D',value=r'') 
+0

Ho provato questo, e non funziona. Mi chiedo se funzioni solo quando si desidera sostituire un'intera stringa invece di sostituire semplicemente una parte della sottostringa. – bgenchel

+0

@bgenchel - Ho usato questo metodo per sostituire parte di una stringa in un file pd.Series: 'df.loc [:, 'column_a']. Replace (regex = True, to_replace =" my_prefix ", value =" new_prefix ") '. Questo convertirà una stringa come "my_prefixaaa" in "new_prefixaaa". – Jakub

5

ho trovato grandi differenze di prestazioni tra i vari metodi per fare le cose come questo (cioè modificando ogni elemento di una serie all'interno di un dataframe). Spesso una lista di comprensione può essere più veloce - vedi gara codice qui sotto:

import pandas as pd 
#Map 
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']}) 
%timeit data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC')) 
10000 loops, best of 3: 187 µs per loop 
#List comprehension 
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']}) 
%timeit data['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in data['result']] 
10000 loops, best of 3: 117 µs per loop 
#.str 
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']}) 
%timeit data['result'] = data['result'].str.lstrip('+-').str.rstrip('aAbBcC') 
1000 loops, best of 3: 336 µs per loop 
+0

Grazie, speravo davvero che qualcuno avesse programmato questi metodi. Queste sono molte buone soluzioni. – griffinc

-8
=RIGHT(LEFT(O13,(LEN(O13)-1)),LEN(LEFT(O13,(LEN(O13)-1))-1)) 

Mettete questo diritto di colonna di risultato e ottenere il risultato.

3

Un metodo molto semplice sarebbe quella di utilizzare il metodo extract per selezionare tutte le cifre. Basta fornire la regolare espressione '\d+' che estrae qualsiasi numero di cifre.

df['result'] = df.result.str.extract('(\d+)', expand=True).astype(int) 
df 

    time result 
1 09:00  52 
2 10:00  62 
3 11:00  44 
4 12:00  30 
5 13:00  110 
Problemi correlati