Видаліть / обріжте всі рядки кадру даних


80

Очищаючи значення багатоканального кадру даних у python / pandas, я хочу обрізати рядки. Зараз я роблю це за двома інструкціями:

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

Це досить повільно, що я міг би покращити?


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

1
Це найкраща відповідь, просто увійдіть, щоб проголосувати за відповідь @MaxU
Linkon

Відповіді:


151

Ви можете використовувати, DataFrame.select_dtypesщоб вибрати stringстовпці, а потім applyфункціонувати str.strip.

Примітка: Цінності не можуть бути typesподібними dictsабо lists, оскільки вони dtypesє 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

Але якщо стовпців лише кілька, використовуйте str.strip:

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

1
І SettingWithCopyWarning у цьому випадку слід ігнорувати, як пояснено stackoverflow.com/questions/20625582/…
Харві

71

Грошовий постріл

Ось компактна версія використання applymapз прямим лямбда-виразом для виклику stripлише тоді, коли значення має тип рядка:

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

Повний приклад

Більш повний приклад:

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

Робочий приклад

Ось робочий приклад, який розміщує брелок: https://trinket.io/python3/e6ab7fb4ab


1
Привіт @DaleKube ... Я щойно спробував це свіже на новій машині просто як перевірку стану розумності, і я отримую ті самі результати, що і розміщені у відповіді. Чи можете ви підтвердити, чи використовуєте ви Python2 чи Python3? Сьогодні я використовую лише Python3, але, можливо, це може бути фактором. Якщо так, я зазначу це у своїй відповіді, якщо ви зможете підтвердити. Дякую!
Джонатан Б.

1
Я видалив свій коментар. Я знайшов помилку в своєму коді, і я можу підтвердити, що вона тепер працює як принада. FYI, я використовую Python 3. Вибачте за біду.
Dale Kube

вам слід користуватися type(x) == str, а неtype(x) is str
fjsj

@fjsj Дякую за підштовхування. Я оновив приклад, використовуючи передумови PEP8 isinstance(x, str).
Джонатан Б.

10

Ви можете спробувати:

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

або більш конкретно для всіх стовпців рядків

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

Якщо ви дійсно хочете використовувати регулярний вираз, тоді

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

Але це має бути швидше, щоб зробити це так:

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

5

Ви можете використовувати applyфункцію від Seriesоб'єкта:

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

Зверніть увагу на те, що використання, stripа не regexяке, набагато швидше

Інший варіант - використовувати applyфункцію об'єкта 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()- швидше за все, буде швидшим на великих
ДФ

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

df = df.apply(trim)

1
Не могли б ви пояснити, що робить функція, будь ласка?
CJ Dennis,

наприклад, я стикаюся з такими даними на своїй щоденній роботі: 가나다 봻 ліва частина порожнього - це те, що я хочу, права частина - сміття. функція trim витягує те, що я хочу, з необроблених даних.
hyunwoo jeong

Проголосовано проти, оскільки це не обрізає рядок, воно видаляє все, що стоїть після першого пробілу. Це не та поведінка, про яку йдеться у питанні, і вводить побічні ефекти, яких читач може не очікувати. Більше того, побічні ефекти можуть виявитися не відразу. Якщо ви намагаєтесь обрізати стовпець прізвищ, ви можете подумати, що це працює належним чином, оскільки більшість людей не мають кількох прізвищ, а кінцеві пробіли видалено. Потім португалець із двома прізвищами приєднується до вашого сайту, і код обробляє їх прізвище, залишаючи лише своє прізвище.
scottclowe
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.