Удаление / обрезка всех строк фрейма данных


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

Ответы:


152

Вы можете использовать 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

Рабочий пример

Вот рабочий пример, размещенный на trinket: https://trinket.io/python3/e6ab7fb4ab


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

1
Я удалил свой комментарий. Я обнаружил ошибку в своем коде и могу подтвердить, что теперь он работает как шарм. К вашему сведению, я использую Python 3. Приносим извинения за проблемы.
Дейл Кубе

ты должен использовать 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()- скорее всего, будет быстрее на больших
DF

-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.