Entfernen / kürzen Sie alle Zeichenfolgen eines Datenrahmens

80

Wenn ich die Werte eines Multitype-Datenrahmens in Python / Pandas bereinige, möchte ich die Zeichenfolgen kürzen. Ich mache es derzeit in zwei Anweisungen:

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

Das ist ziemlich langsam, was könnte ich verbessern?

mxdbld
quelle
1
df.replace(r'\s*(.*?)\s*', r'\1', regex=True)
MaxU
1
Dies ist die beste Antwort. Sie haben sich gerade angemeldet, um die Antwort von @MaxU
Linkon

Antworten:

147

Sie können Spalten DataFrame.select_dtypesauswählen stringund dann applyfunktionieren str.strip.

Hinweis: Werte können nicht typeswie dictsoder sein lists, weil sie dtypessind object.

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

Aber wenn es nur wenige Spalten gibt, verwenden Sie str.strip:

df[0] = df[0].str.strip()
jezrael
quelle
1
Und SettingWithCopyWarning sollte in diesem Fall ignoriert werden, wie unter stackoverflow.com/questions/20625582/…
Harvey
67

Geldschuss

Hier ist eine kompakte Version der Verwendung applymapmit einem einfachen Lambda-Ausdruck, die stripnur aufgerufen wird , wenn der Wert vom Typ einer Zeichenfolge ist:

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

Vollständiges Beispiel

Ein vollständigeres Beispiel:

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

Arbeitsbeispiel

Hier ist ein Arbeitsbeispiel, das von trinket gehostet wird: https://trinket.io/python3/e6ab7fb4ab

Jonathan B.
quelle
1
Hi @DaleKube ... Ich habe es gerade auf einem neuen Computer ausprobiert, nur um die Gesundheit zu überprüfen, und ich erhalte die gleichen Ergebnisse wie in der Antwort angegeben. Können Sie bestätigen, ob Sie Python2 oder Python3 verwenden? Ich benutze heutzutage nur Python3, aber vielleicht könnte das ein Faktor sein. Wenn ja, werde ich dies in meiner Antwort vermerken, wenn Sie dies bestätigen können. Vielen Dank!
Jonathan B.
1
Ich habe meinen Kommentar gelöscht. Ich habe einen Fehler in meinem Code gefunden und kann bestätigen, dass er jetzt wie ein Zauber funktioniert. Zu Ihrer Information, ich verwende Python 3. Entschuldigen Sie die Probleme.
Dale Kube
Sie sollten verwenden type(x) == str, nichttype(x) is str
fjsj
@fjsj Danke für den Schubs. Ich habe das Beispiel mithilfe der PEP8-Anleitung aktualisiert isinstance(x, str).
Jonathan B.
10

Du kannst es versuchen:

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

oder genauer für alle Zeichenfolgenspalten

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())
Aakash Makwana
quelle
9

Wenn Sie Regex wirklich verwenden möchten, dann

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

Aber es sollte schneller gehen, um es so zu machen:

>>> df[0] = df[0].str.strip()
Roman Pekar
quelle
5

Sie können die applyFunktion des SeriesObjekts verwenden:

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

Beachten Sie die Verwendung von stripund nicht die, regexdie viel schneller ist

Eine weitere Option - verwenden Sie die applyFunktion des DataFrame-Objekts:

>>> 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
Dekel
quelle
1
df[0] = df[0].str.strip()- wird höchstwahrscheinlich auf größeren DFs schneller sein
MaxU
-1
def trim(x):
    if x.dtype == object:
        x = x.str.split(' ').str[0]
    return(x)

df = df.apply(trim)
Hyunwoo Jeong
quelle
1
Können Sie bitte erklären, was die Funktion tut?
CJ Dennis
Zum Beispiel stoße ich in meinem täglichen Job auf solche Daten: Der 가나다 봻 linke Teil des Leerzeichens ist das, was ich will, der rechte Teil ist Müll. Trimmfunktion extrahieren, was ich aus Rohdaten will.
Hyunwoo Jeong
Da dies die Zeichenfolge nicht trimmt, wird alles entfernt, was nach dem ersten Leerzeichen folgt. Dies ist nicht das Verhalten, nach dem in der Frage gefragt wird, und führt zu Nebenwirkungen, die ein Leser möglicherweise nicht erwartet. Darüber hinaus sind die Nebenwirkungen möglicherweise nicht sofort erkennbar. Wenn Sie versuchen, eine Spalte mit Nachnamen zu kürzen, denken Sie möglicherweise, dass dies wie beabsichtigt funktioniert, da die meisten Benutzer nicht über mehrere Nachnamen verfügen und nachgestellte Leerzeichen ja entfernt werden. Dann tritt eine portugiesische Person mit zwei Nachnamen Ihrer Website bei und der Code schneidet ihren Nachnamen weg, wobei nur ihr Vorname übrig bleibt.
Scottclowe