2015-11-18 14 views
11

Czytam plik CSV w DataFrame. Muszę usunąć białe znaki ze wszystkich podobnych do łańcucha komórek, pozostawiając pozostałe komórki w niezmienionej postaci w Pythonie 2.7.Pythoniczny/efektywny sposób na usunięcie białych znaków z każdej komórki ramki danych Pandas, która ma w niej obiekt podobny do łańcucha znaków

Oto co robię:

def remove_whitespace(x): 
    if isinstance(x, basestring): 
     return x.strip() 
    else: 
     return x 

my_data = my_data.applymap(remove_whitespace) 

Czy jest lepszy lub bardziej idiomatycznych do Pandy sposób to zrobić?

Czy jest bardziej efektywny sposób (być może robiąc rzeczy w mądrych kolumnach)?

Próbowałem już znaleźć ostateczną odpowiedź, ale większość pytań na ten temat brzmi: jak usunąć białe znaki z nazw kolumn lub założyć, że wszystkie komórki są ciągami.

+0

Co by się stało, gdybyś zrobił x.strip() na elemencie, który nie jest instancją łańcucha bazowego? Jeśli nie ma żadnych wad, możesz usunąć test i zastąpić go blokiem try i except. To może przyspieszyć sytuację. –

+2

Czy używasz 'pandas.read_csv' (http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.read_csv.html)? Czy próbowałeś 'skipinitialspace = True'? –

+0

@WarrenWeckesser Mogę mieć białe spacje zarówno przed jak i po danych, na których mi zależy w komórce, więc myślę, że skipinitialspace naprawia tylko połowę problemu. – deadcode

Odpowiedz

16

Można użyć pandy Series.str.strip() sposób to zrobić szybko dla każdej kolumnie ciąg podobny:

>>> data = pd.DataFrame({'values': [' ABC ', ' DEF', ' GHI ']}) 
>>> data 
     values 
0  ABC 
1  DEF 
2  GHI 

>>> data['values'].str.strip() 
0 ABC 
1 DEF 
2 GHI 
Name: values, dtype: object 
3

Po wywołaniu pandas.read_csv, można użyć wyrażenia regularnego, które dopasowuje zero lub więcej spacji następnie przecinkami następnie zero lub więcej spacji jako separatora.

Na przykład, oto "data.csv":

In [19]: !cat data.csv 
1.5, aaa, bbb , ddd  , 10 , XXX 
2.5, eee, fff ,  ggg, 20 ,  YYY 

(Pierwsza linia kończy z trzech miejsc po XXX, natomiast druga linia kończy się na ostatnim Y.)

następujących zastosowań pandas.read_csv() przeczytać pliki, z wyrażeniem regularnym ' *, *' jako ogranicznikiem. (Korzystanie z wyrażeń regularnych jako separator jest dostępna tylko w „python” silnika read_csv().)

In [20]: import pandas as pd 

In [21]: df = pd.read_csv('data.csv', header=None, delimiter=' *, *', engine='python') 

In [22]: df 
Out[22]: 
    0 1 2 3 4 5 
0 1.5 aaa bbb ddd 10 XXX 
1 2.5 eee fff ggg 20 YYY 
+1

To jest bardzo blisko, ale ma problem z cytowanymi wartościami wejściowymi, takimi jak: "a, b, c", d Nie może wyciągnąć spacji z pierwszego pola, które chciałbym zapisać w komórce danych jako "a, b, c" – deadcode

1

„Dane wartości [«»]. Str.strip()” odpowiedzieć na powyższe nie działa dla mnie , ale znalazłem prostą pracę. Jestem pewien, że jest lepszy sposób na zrobienie tego. Funkcja str.strip() działa w Serii. W ten sposób przekonwertowałem kolumnę siatki danych na serię, usunięto białe znaki, zastąpiłem przekształconą kolumnę z powrotem w ramkę danych. Poniżej znajduje się przykładowy kod.

import pandas as pd 
data = pd.DataFrame({'values': [' ABC ', ' DEF', ' GHI ']}) 
print ('-----') 
print (data) 

data['values'].str.strip() 
print ('-----') 
print (data) 

new = pd.Series([]) 
new = data['values'].str.strip() 
data['values'] = new 
print ('-----') 
print (new) 
0

Oto kolumna-wise rozwiązanie z zastosowania pandy:

import numpy as np 

def strip_obj(col): 
    if col.dtypes == object: 
     return (col.astype(str) 
        .str.strip() 
        .replace({'nan': np.nan})) 
    return col 

df = df.apply(strip_obj, axis=0) 

To będzie konwertować wartości w kolumnach typu obiektu do łańcucha. Należy zachować ostrożność w przypadku kolumn mieszanych. Na przykład, jeśli twoja kolumna jest kod pocztowy z 20001 i "21110", otrzymasz "20001" i "21110".

8

Natknąłem się na to pytanie, szukając szybkiego i minimalistycznego fragmentu, którego mógłbym użyć. Musiałem samemu złożyć go ze stanowisk powyżej. Może ktoś uzna to za przydatne:

data_frame_trimmed = data_frame.apply(lambda x: x.str.strip() if x.dtype == "object" else x) 
Powiązane problemy