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?


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()

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


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())

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()

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

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)

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.