Видалення кількох стовпців на основі назв стовпців у Pandas


94

У мене є деякі дані, і коли я їх імпортую, я отримую такі непотрібні стовпці, я шукаю простий спосіб видалити всі ці

   'Unnamed: 24', 'Unnamed: 25', 'Unnamed: 26', 'Unnamed: 27',
   'Unnamed: 28', 'Unnamed: 29', 'Unnamed: 30', 'Unnamed: 31',
   'Unnamed: 32', 'Unnamed: 33', 'Unnamed: 34', 'Unnamed: 35',
   'Unnamed: 36', 'Unnamed: 37', 'Unnamed: 38', 'Unnamed: 39',
   'Unnamed: 40', 'Unnamed: 41', 'Unnamed: 42', 'Unnamed: 43',
   'Unnamed: 44', 'Unnamed: 45', 'Unnamed: 46', 'Unnamed: 47',
   'Unnamed: 48', 'Unnamed: 49', 'Unnamed: 50', 'Unnamed: 51',
   'Unnamed: 52', 'Unnamed: 53', 'Unnamed: 54', 'Unnamed: 55',
   'Unnamed: 56', 'Unnamed: 57', 'Unnamed: 58', 'Unnamed: 59',
   'Unnamed: 60'

Вони індексуються за допомогою 0-індексації, тому я спробував щось на зразок

    df.drop(df.columns[[22, 23, 24, 25, 
    26, 27, 28, 29, 30, 31, 32 ,55]], axis=1, inplace=True)

Але це не дуже ефективно. Я спробував написати кілька для циклів, але це видалося мені поганою поведінкою панди. Тому я задаю питання тут.

Я бачив кілька подібних прикладів ( Викиньте кілька стовпців панд ), але це не відповідає на моє запитання.


2
Що ви маєте на увазі, ефективно? Це працює занадто повільно? Якщо ваша проблема полягає в тому, що ви не хочете отримувати індекси всіх стовпців, які ви хочете видалити, зверніть увагу, що ви можете просто вказати df.dropсписок назв стовпців:df.drop(['Unnamed: 24', 'Unnamed: 25', ...], axis=1)
— Карстен

Чи не було б простіше просто df = df[cols_of_interest]df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)
— підставити

2
Я мав на увазі неефективний з точки зору набору тексту або "поганий запах коду"
— Peadar Coyle,

1
Можливо, варто зазначити, що в більшості випадків простіше просто зберегти потрібні стовпці, а потім видалити ті, яких ви не робите: df = df ['col_list']
— воробей

Відповіді:


65

Я не знаю, що ви маєте на увазі під неефективним, але якщо ви маєте на увазі терміни набору тексту, то може бути простіше просто вибрати зацікавлені колонки і призначити назад df:

df = df[cols_of_interest]

Де cols_of_interestсписок стовпців, які вас цікавлять.

Або ви можете нарізати стовпці та передати це drop:

df.drop(df.ix[:,'Unnamed: 24':'Unnamed: 60'].head(0).columns, axis=1)

Виклик headпросто вибирає 0 рядків, оскільки нас цікавлять лише назви стовпців, а не дані

оновлення

Інший метод: було б простіше використовувати логічну маску str.containsта інвертувати її для маскування стовпців:

In [2]:
df = pd.DataFrame(columns=['a','Unnamed: 1', 'Unnamed: 1','foo'])
df

Out[2]:
Empty DataFrame
Columns: [a, Unnamed: 1, Unnamed: 1, foo]
Index: []

In [4]:
~df.columns.str.contains('Unnamed:')

Out[4]:
array([ True, False, False,  True], dtype=bool)

In [5]:
df[df.columns[~df.columns.str.contains('Unnamed:')]]

Out[5]:
Empty DataFrame
Columns: [a, foo]
Index: []

Я отримую помилки, коли намагаюся виконати або ~ df.columns ... (TypeError: поганий тип операнда для унарного ~: 'str'), або df.columns.str.contains ... (AttributeError: 'Index' об'єкт не має атрибута 'str'). Будь-які ідеї, чому це може бути?
— Dai

@EdChum чи можу я створити df = df [cols_of_interest] , де cols_of_interest кожен раз додає до нього назву стовпця, коли цикл for повторюється?

@Victor ні, якщо ви зробите так, що ви перезапишете ваш dfновий стовпець, appendможливо, але я насправді не розумію ваше запитання, вам слід публікувати справжнє запитання на SO, а не запитувати як коментар, оскільки це погана форма на SO
— EdChum

@EdChum ви абсолютно праві. Я створив запитання і намагаюся вирішити його, шукаючи різні частини SO. Ось посилання! будь-який внесок допоможе stackoverflow.com/questions/48923915 / ...

212

На сьогоднішній день найпростішим підходом є:

yourdf.drop(['columnheading1', 'columnheading2'], axis=1, inplace=True)

1
Я використовував цей формат у деяких своїх кодах і отримую SettingWithCopyWarningпопередження?
— KillerSnail

2
@KillerSnail, це ігнорувати збереження. Щоб уникнути помилки, спробуйте: df = df.drop (['colheading1', 'colheading2'], axis = 1)
— Філіп Шварц

5
axisПояснюваний термін : stackoverflow.com/questions/22149584/… . По суті, axis=0кажуть, що він "стовпець" і axis=1"рядок".
— Ромер,

5
І inplace=Trueозначає, що DataFrameмодифікований на місці.
— Ромер,

1
@Killernail, якщо ти не хочеш попередження, робиyourdf = yourdf.drop(['columnheading1', 'columnheading2'], axis=1)
— happy_sisyphus

41

Мій особистий улюблений і простіший за відповіді, які я бачив тут (для кількох стовпців):

df.drop(df.columns[22:56], axis=1, inplace=True)

Або створення списку для кількох стовпців.

col = list(df.columns)[22:56]
df.drop(col, axis=1, inplace=1)

8
Це має бути відповіддю. Найчистіший, найпростіший для читання, з простим синтаксисом індексації рідних панд.
— Брент Фауст,

2
Ця відповідь повинна мати зелену галочку поруч, а не інші.
— Siavosh Mahboubian

1
Невелике виправлення (якщо я не помиляюсь): другий блок коду повинен мати "inplace = True" замість "inplace = 1".
— Тредольсен

20

Це, мабуть, хороший спосіб зробити те, що ти хочеш. Буде видалено всі стовпці, які містять у назві "Без імені".

for col in df.columns:
    if 'Unnamed' in col:
        del df[col]

це for col in df.columns:можна спростити for col in df:, також в OP не вказано, що таке схема іменування для інших стовпців, всі вони можуть містити "Без імені", також це неефективно, оскільки видаляє стовпці по черзі
— EdChum

Це, звичайно, не ефективно, але поки ми не працюємо над величезними кадрами даних, це не матиме значного впливу. Плюсом цього методу є те, що його легко запам’ятати і швидко кодувати - при створенні списку стовпців, які ви хочете зберегти, може бути досить боляче.
— knightofni

Я думаю, що це, швидше за все, буде найефективнішим на великому df, тому що вам не потрібно робити локальну копію за допомогоюinplace = True
— Метт

13

Ви можете зробити це в один рядок і одним рухом:

df.drop([col for col in df.columns if "Unnamed" in col], axis=1, inplace=True)

Це передбачає менше переміщення / копіювання об’єкта, ніж рішення вище.


11

Не впевнений, що це рішення ще десь згадувалось, але один із способів це зробити pandas.Index.difference.

>>> df = pd.DataFrame(columns=['A','B','C','D'])
>>> df
Empty DataFrame
Columns: [A, B, C, D]
Index: []
>>> to_remove = ['A','C']
>>> df = df[df.columns.difference(to_remove)]
>>> df
Empty DataFrame
Columns: [B, D]
Index: []

4

Ви можете просто передати імена стовпців як список із зазначенням осі як 0 або 1

  • вісь = 1: уздовж рядків
  • вісь = 0: уздовж стовпців
  • За замовчуванням вісь = 0

    data.drop(["Colname1","Colname2","Colname3","Colname4"],axis=1)


4

Простий і легкий. Видаліть усі стовпці після 22 числа.

df.drop(columns=df.columns[22:]) # love it

Щоб змінити dfна місці, додайте прапор inplace=True, так щоdf.drop(columns=df.columns[22:], inplace=True)
— arilwan

1

Мені працювало нижче:

for col in df:
    if 'Unnamed' in col:
        #del df[col]
        print col
        try:
            df.drop(col, axis=1, inplace=True)
        except Exception:
            pass

0

df = df[[col for col in df.columns if not ('Unnamed' in col)]]


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