Видалення кількох стовпців на основі назв стовпців у 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.