Usuń / przycinaj wszystkie ciągi ramki danych


80

Czyszczenie wartości ramki danych typu multitype w python / pandas, chcę przyciąć ciągi. Obecnie robię to w dwóch instrukcjach:

import pandas as pd

df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])

df.replace('^\s+', '', regex=True, inplace=True) #front
df.replace('\s+$', '', regex=True, inplace=True) #end

df.values

To jest dość powolne, co mogę poprawić?


1
df.replace(r'\s*(.*?)\s*', r'\1', regex=True)
MaxU

1
To jest najlepsza odpowiedź, właśnie zalogowałem się, aby zagłosować na odpowiedź przez @MaxU
Linkon

Odpowiedzi:


152

Możesz użyć DataFrame.select_dtypesdo zaznaczenia stringkolumn, a następnie applyfunkcji str.strip.

Uwaga: Wartości nie mogą być typestakie jak dictslub lists, ponieważ dtypesobject.

df_obj = df.select_dtypes(['object'])
print (df_obj)
0    a  
1    c  

df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip())
print (df)

   0   1
0  a  10
1  c   5

Ale jeśli jest tylko kilka kolumn, użyj str.strip:

df[0] = df[0].str.strip()

1
I SettingWithCopyWarning należy zignorować w tym przypadku, jak wyjaśniono stackoverflow.com/questions/20625582/ ...
Harvey,

71

Zastrzyk gotówki

Oto kompaktowa wersja użycia applymapz prostym wyrażeniem lambda do wywołania striptylko wtedy, gdy wartość jest typu string:

df.applymap(lambda x: x.strip() if isinstance(x, str) else x)

Pełny przykład

Bardziej kompletny przykład:

import pandas as pd


def trim_all_columns(df):
    """
    Trim whitespace from ends of each value across all series in dataframe
    """
    trim_strings = lambda x: x.strip() if isinstance(x, str) else x
    return df.applymap(trim_strings)


# simple example of trimming whitespace from data elements
df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])
df = trim_all_columns(df)
print(df)


>>>
   0   1
0  a  10
1  c   5

Przykład roboczy

Oto działający przykład hostowany przez trinket: https://trinket.io/python3/e6ab7fb4ab


1
Cześć, @DaleKube ... Właśnie wypróbowałem to na nowej maszynie jako test poczytalności i otrzymałem takie same wyniki, jak podano w odpowiedzi. Czy możesz potwierdzić, czy używasz Python2 czy Python3? Obecnie używam tylko Pythona3, ale być może to może mieć znaczenie. Jeśli tak, zauważę to w mojej opublikowanej odpowiedzi, jeśli możesz to potwierdzić. Dzięki!
Jonathan B.

1
Usunąłem swój komentarz. Znalazłem błąd w moim kodzie i mogę potwierdzić, że teraz działa jak urok. FYI, używam Pythona 3. Przepraszamy za kłopoty.
Dale Kube

powinieneś używać type(x) == str, a nietype(x) is str
fjsj

@fjsj Dzięki za ponaglenie. Zaktualizowałem przykład przy użyciu faworyzowania wskazówek PEP8 isinstance(x, str).
Jonathan B.

10

Możesz spróbować:

df[0] = df[0].str.strip()

a dokładniej dla wszystkich kolumn ciągów

non_numeric_columns = list(set(df.columns)-set(df._get_numeric_data().columns))
df[non_numeric_columns] = df[non_numeric_columns].apply(lambda x : str(x).strip())

9

Jeśli naprawdę chcesz użyć wyrażenia regularnego, to

>>> df.replace('(^\s+|\s+$)', '', regex=True, inplace=True)
>>> df
   0   1
0  a  10
1  c   5

Ale powinno być szybsze zrobienie tego w ten sposób:

>>> df[0] = df[0].str.strip()

5

Można korzystać z applyfunkcji tego Seriesobiektu:

>>> df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])
>>> df[0][0]
'  a  '
>>> df[0] = df[0].apply(lambda x: x.strip())
>>> df[0][0]
'a'

Zwróć uwagę na użycie, stripa nie to, regexco jest znacznie szybsze

Inna opcja - skorzystaj z applyfunkcji obiektu DataFrame:

>>> df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])
>>> df.apply(lambda x: x.apply(lambda y: y.strip() if type(y) == type('') else y), axis=0)

   0   1
0  a  10
1  c   5

1
df[0] = df[0].str.strip()- najprawdopodobniej będzie szybszy na większych DF
MaxU

-1
def trim(x):
    if x.dtype == object:
        x = x.str.split(' ').str[0]
    return(x)

df = df.apply(trim)

1
Czy mógłbyś wyjaśnić, co robi ta funkcja?
CJ Dennis

na przykład w mojej codziennej pracy napotykam takie dane: 가나다 봻 lewa część pusta jest tym, czego chcę, prawa część to śmieci. funkcja przycinania wyodrębnia to, co chcę z surowych danych.
hyunwoo jeong

Obniżony, ponieważ nie powoduje to obcięcia ciągu, usuwa wszystko, co następuje po pierwszej spacji. Nie jest to zachowanie wymagane w pytaniu i wprowadza skutki uboczne, których czytelnik może się nie spodziewać. Ponadto skutki uboczne mogą nie być od razu widoczne. Jeśli próbujesz przyciąć kolumnę nazwisk, możesz pomyśleć, że działa to zgodnie z przeznaczeniem, ponieważ większość ludzi nie ma wielu nazwisk, a spacje na końcu są tak usunięte. Następnie Portugalczyk z dwoma nazwiskami dołącza do Twojej witryny, a kod odcina ich ostatnie nazwisko, pozostawiając tylko pierwsze nazwisko.
scottclowe
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.