Удалить столбец из панды DataFrame

При удалении столбца в DataFrame я использую:

del df['column_name']

И это прекрасно работает. Почему я не могу использовать следующее?

del df.column_name

Поскольку вы можете получить доступ к столбцу/Серии как df.column_name, я ожидаю, что это сработает.

Ответы

Ответ 1

Как вы уже догадались, правильный синтаксис

del df['column_name']

Трудно заставить del df.column_name работать просто из-за синтаксических ограничений в Python. del df[name] переводится в df.__delitem__(name) под прикрытием Python.

Ответ 2

Лучший способ сделать это в пандах - использовать drop:

df = df.drop('column_name', 1)

где 1 - номер оси (0 для строк и 1 для столбцов.)

Чтобы удалить столбец без переназначения df вы можете сделать:

df.drop('column_name', axis=1, inplace=True)

Наконец, чтобы перейти по номеру столбца, а не по метке столбца, попробуйте это удалить, например, 1-й, 2-й и 4-й столбцы:

df = df.drop(df.columns[[0, 1, 3]], axis=1)  # df.columns is zero-based pd.Index 

Ответ 3

Использование:

columns = ['Col1', 'Col2', ...]
df.drop(columns, inplace=True, axis=1)

Это удалит один или несколько столбцов на месте. Обратите внимание, что inplace=True был добавлен в pandas v0.13 и не будет работать на старых версиях. Вы должны были бы присвоить результат обратно в этом случае:

df = df.drop(columns, axis=1)

Ответ 4

Падение по индексу

Удалить первый, второй и четвертый столбцы:

df.drop(df.columns[[0,1,3]], axis=1, inplace=True)

Удалить первый столбец:

df.drop(df.columns[[0]], axis=1, inplace=True)

Существует дополнительный параметр inplace так, что исходные данные могут быть изменены без создания копии.

Выскочил

Выбор, добавление, удаление столбцов

Удалить столбец column-name:

df.pop('column-name')

Примеры:

df = DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6]), ('C', [7,8, 9])], orient='index', columns=['one', 'two', 'three'])

print df:

   one  two  three
A    1    2      3
B    4    5      6
C    7    8      9

df.drop(df.columns[[0]], axis=1, inplace=True) print df:

   two  three
A    2      3
B    5      6
C    8      9

three = df.pop('three') print df:

   two
A    2
B    5
C    8

Ответ 5

Фактический вопрос, который пропущен большинством ответов здесь:

Почему я не могу использовать del df.column_name?

Сначала нам нужно понять проблему, которая требует от нас погрузиться в магические методы Python.

Как указывает Уэс в своем ответе, del df['column'] отображается на магический метод python df.__delitem__('column') который реализован в pandas для удаления столбца.

Однако, как указано в ссылке выше о магических методах Python:

Фактически, del почти никогда не должен использоваться из-за сомнительных обстоятельств, при которых он вызывается; используйте это с осторожностью!

Вы можете утверждать, что del df['column_name'] не следует использовать или поощрять, и, следовательно, del df.column_name даже не следует рассматривать.

Однако теоретически del df.column_name может быть реализован для работы в пандах с использованием магического метода __delattr__. Это, однако, создает определенные проблемы, проблемы, которые уже есть у реализации del df['column_name'], но в меньшей степени.

Пример задачи

Что если я определю столбец в кадре данных, который называется "dtypes" или "columns".

Тогда предположим, что я хочу удалить эти столбцы.

del df.dtypes бы в __delattr__ метод __delattr__ как если бы он удалил атрибут "dtypes" или столбец "dtypes".

Архитектурные вопросы, стоящие за этой проблемой

  1. Является ли датафрейм коллекцией столбцов?
  2. Является ли датафрейм набором строк?
  3. Является ли столбец атрибутом кадра данных?

Панда отвечает:

  1. Да, во всех отношениях
  2. Нет, но если вы хотите, чтобы это было, вы можете использовать .ix, .loc или .iloc.
  3. Может быть, вы хотите прочитать данные? Тогда да, если только имя атрибута не занято другим атрибутом, принадлежащим фрейму данных. Вы хотите изменить данные? Тогда нет.

TL;DR;

Вы не можете использовать del df.column_name потому что у pandas довольно del df.column_name архитектура, которую необходимо пересмотреть, чтобы такого рода когнитивный диссонанс не возникал у пользователей.

Protip:

Не используйте df.column_name, это может быть красиво, но это вызывает когнитивный диссонанс

Цитаты Zen of Python, которые здесь вписываются:

Существует несколько способов удаления столбца.

Должен быть one-- и, предпочтительно, только один --obvious способ сделать это.

Столбцы иногда являются атрибутами, но иногда нет.

Особые случаи не достаточно особенные, чтобы нарушать правила.

del df.dtypes ли del df.dtypes атрибут dtypes или столбец dtypes?

Перед лицом двусмысленности откажитесь от соблазна гадать.

Ответ 6

Приятным дополнением является возможность отбрасывать столбцы, только если они существуют. Таким образом, вы можете охватить больше вариантов использования, и он удалит только существующие столбцы из меток, переданных ему:

Просто добавьте ошибки = "игнорировать", например:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Это новинка от панд 0.16.1 и выше. Документация здесь.

Ответ 7

из версии 0.16.1 вы можете сделать

df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')

Ответ 8

Рекомендуется всегда использовать нотацию []. Одна из причин заключается в том, что нотация атрибута (df.column_name) не работает для пронумерованных индексов:

In [1]: df = DataFrame([[1, 2, 3], [4, 5, 6]])

In [2]: df[1]
Out[2]:
0    2
1    5
Name: 1

In [3]: df.1
  File "<ipython-input-3-e4803c0d1066>", line 1
    df.1
       ^
SyntaxError: invalid syntax

Ответ 9

В pandas 0.16.1+ вы можете оставить столбцы только в том случае, если они существуют для решения, отправленного @eiTanLaVi. До этой версии вы можете добиться того же результата с помощью условного списка:

df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df], 
        axis=1, inplace=True)

Ответ 10

Панды 0. 21+ ответ

Панды версия 0,21 изменил drop метод немного включать как index и columns параметров в соответствии сигнатуру rename и reindex методов.

df.drop(columns=['column_a', 'column_c'])

Лично я предпочитаю использовать параметр axis для обозначения столбцов или индекса, потому что это основной параметр ключевого слова, используемый почти во всех методах панд. Но теперь у вас есть несколько добавленных вариантов в версии 0.21.

Ответ 11

Вы должны использовать drop(). Предположим, что ваше имя файловой системы - df.

#for dropping single column 
df = df.drop('your_column', axis=1)

#for dropping multiple columns
df = df.drop(['col_1','col_2','col_3'], axis=1)

Ответ 12

TL; DR

Много усилий, чтобы найти немного более эффективное решение. Трудно оправдать добавленную сложность, жертвуя простотой df.drop(dlst, 1, errors='ignore')

df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)

Преамбула
Удаление столбца семантически совпадает с выбором других столбцов. Я покажу несколько дополнительных методов для рассмотрения.

Я также сосредоточусь на общем решении по удалению нескольких столбцов одновременно и позволяя удалять столбцы, которые не присутствуют.

Использование этих решений является общим и будет работать и для простого случая.


Настройка
Рассмотрим pd.DataFrame df и список для удаления dlst

df = pd.DataFrame(dict(zip('ABCDEFGHIJ', range(1, 11))), range(3))
dlst = list('HIJKLM')

df

   A  B  C  D  E  F  G  H  I   J
0  1  2  3  4  5  6  7  8  9  10
1  1  2  3  4  5  6  7  8  9  10
2  1  2  3  4  5  6  7  8  9  10

dlst

['H', 'I', 'J', 'K', 'L', 'M']

Результат должен выглядеть так:

df.drop(dlst, 1, errors='ignore')

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

Поскольку я приравниваю удаление столбца к выбору других столбцов, я разбиваю его на два типа:

  • Выбор метки
  • Логический выбор

Выбор метки

Мы начинаем с создания списка/массива меток, которые представляют столбцы, которые мы хотим сохранить, и без столбцов, которые мы хотим удалить.

  • df.columns.difference(dlst)

    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
    
  • np.setdiff1d(df.columns.values, dlst)

    array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype=object)
    
  • df.columns.drop(dlst, errors='ignore')

    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
    
  • list(set(df.columns.values.tolist()).difference(dlst))

    # does not preserve order
    ['E', 'D', 'B', 'F', 'G', 'A', 'C']
    
  • [x for x in df.columns.values.tolist() if x not in dlst]

    ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    

Столбцы с надписью
Для сравнения процесса выбора предположим:

 cols = [x for x in df.columns.values.tolist() if x not in dlst]

Тогда мы можем оценить

  • df.loc[:, cols]
  • df[cols]
  • df.reindex(columns=cols)
  • df.reindex_axis(cols, 1)

Что все оценивают по:

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

Булевский фрагмент

Мы можем построить массив/список булевых элементов для нарезки

  • ~df.columns.isin(dlst)
  • ~np.in1d(df.columns.values, dlst)
  • [x not in dlst for x in df.columns.values.tolist()]
  • (df.columns.values[:, None] != dlst).all(1)

Столбцы из булева
Для сравнения

bools = [x not in dlst for x in df.columns.values.tolist()]
  • df.loc[: bools]

Что все оценивают по:

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

Надежное время

Функции

setdiff1d = lambda df, dlst: np.setdiff1d(df.columns.values, dlst)
difference = lambda df, dlst: df.columns.difference(dlst)
columndrop = lambda df, dlst: df.columns.drop(dlst, errors='ignore')
setdifflst = lambda df, dlst: list(set(df.columns.values.tolist()).difference(dlst))
comprehension = lambda df, dlst: [x for x in df.columns.values.tolist() if x not in dlst]

loc = lambda df, cols: df.loc[:, cols]
slc = lambda df, cols: df[cols]
ridx = lambda df, cols: df.reindex(columns=cols)
ridxa = lambda df, cols: df.reindex_axis(cols, 1)

isin = lambda df, dlst: ~df.columns.isin(dlst)
in1d = lambda df, dlst: ~np.in1d(df.columns.values, dlst)
comp = lambda df, dlst: [x not in dlst for x in df.columns.values.tolist()]
brod = lambda df, dlst: (df.columns.values[:, None] != dlst).all(1)

Тестирование

res1 = pd.DataFrame(
    index=pd.MultiIndex.from_product([
        'loc slc ridx ridxa'.split(),
        'setdiff1d difference columndrop setdifflst comprehension'.split(),
    ], names=['Select', 'Label']),
    columns=[10, 30, 100, 300, 1000],
    dtype=float
)

res2 = pd.DataFrame(
    index=pd.MultiIndex.from_product([
        'loc'.split(),
        'isin in1d comp brod'.split(),
    ], names=['Select', 'Label']),
    columns=[10, 30, 100, 300, 1000],
    dtype=float
)

res = res1.append(res2).sort_index()

dres = pd.Series(index=res.columns, name='drop')

for j in res.columns:
    dlst = list(range(j))
    cols = list(range(j // 2, j + j // 2))
    d = pd.DataFrame(1, range(10), cols)
    dres.at[j] = timeit('d.drop(dlst, 1, errors="ignore")', 'from __main__ import d, dlst', number=100)
    for s, l in res.index:
        stmt = '{}(d, {}(d, dlst))'.format(s, l)
        setp = 'from __main__ import d, dlst, {}, {}'.format(s, l)
        res.at[(s, l), j] = timeit(stmt, setp, number=100)

rs = res / dres

rs

                          10        30        100       300        1000
Select Label                                                           
loc    brod           0.747373  0.861979  0.891144  1.284235   3.872157
       columndrop     1.193983  1.292843  1.396841  1.484429   1.335733
       comp           0.802036  0.732326  1.149397  3.473283  25.565922
       comprehension  1.463503  1.568395  1.866441  4.421639  26.552276
       difference     1.413010  1.460863  1.587594  1.568571   1.569735
       in1d           0.818502  0.844374  0.994093  1.042360   1.076255
       isin           1.008874  0.879706  1.021712  1.001119   0.964327
       setdiff1d      1.352828  1.274061  1.483380  1.459986   1.466575
       setdifflst     1.233332  1.444521  1.714199  1.797241   1.876425
ridx   columndrop     0.903013  0.832814  0.949234  0.976366   0.982888
       comprehension  0.777445  0.827151  1.108028  3.473164  25.528879
       difference     1.086859  1.081396  1.293132  1.173044   1.237613
       setdiff1d      0.946009  0.873169  0.900185  0.908194   1.036124
       setdifflst     0.732964  0.823218  0.819748  0.990315   1.050910
ridxa  columndrop     0.835254  0.774701  0.907105  0.908006   0.932754
       comprehension  0.697749  0.762556  1.215225  3.510226  25.041832
       difference     1.055099  1.010208  1.122005  1.119575   1.383065
       setdiff1d      0.760716  0.725386  0.849949  0.879425   0.946460
       setdifflst     0.710008  0.668108  0.778060  0.871766   0.939537
slc    columndrop     1.268191  1.521264  2.646687  1.919423   1.981091
       comprehension  0.856893  0.870365  1.290730  3.564219  26.208937
       difference     1.470095  1.747211  2.886581  2.254690   2.050536
       setdiff1d      1.098427  1.133476  1.466029  2.045965   3.123452
       setdifflst     0.833700  0.846652  1.013061  1.110352   1.287831

fig, axes = plt.subplots(2, 2, figsize=(8, 6), sharey=True)
for i, (n, g) in enumerate([(n, g.xs(n)) for n, g in rs.groupby('Select')]):
    ax = axes[i // 2, i % 2]
    g.plot.bar(ax=ax, title=n)
    ax.legend_.remove()
fig.tight_layout()

Это относится к времени, которое требуется для запуска df.drop(dlst, 1, errors='ignore'). Похоже, что после всех этих усилий мы только улучшаем производительность скромно.

введите описание изображения здесь

Если на самом деле лучшие решения используют reindex или reindex_axis на хаке list(set(df.columns.values.tolist()).difference(dlst)). Ближайшая секунда и все еще очень незначительно лучше, чем drop равна np.setdiff1d.

rs.idxmin().pipe(
    lambda x: pd.DataFrame(
        dict(idx=x.values, val=rs.lookup(x.values, x.index)),
        x.index
    )
)

                      idx       val
10     (ridx, setdifflst)  0.653431
30    (ridxa, setdifflst)  0.746143
100   (ridxa, setdifflst)  0.816207
300    (ridx, setdifflst)  0.780157
1000  (ridxa, setdifflst)  0.861622

Ответ 13

Если вы хотите удалить один столбец (col_name) из кадра данных (df), попробуйте выполнить одно из следующих действий:

df = df.drop(col_name, axis=1)

ИЛИ ЖЕ

df.drop(col_name, axis=1, inplace=True)

Если вы хотите удалить список столбцов (col_lst = [col_name_1,col_name_2,...]) из фрейма данных (df), попробуйте col_lst = [col_name_1,col_name_2,...] одно из следующих действий:

df.drop(col_lst, axis=1, inplace=True)

ИЛИ ЖЕ

df.drop(columns=col_lst, inplace=True)

Ответ 14

Точечный синтаксис работает в JavaScript, но не в Python.

  • Python: del df['column_name']
  • JavaScript: del df['column_name'] или del df.column_name

Ответ 15

попробуйте это, я думаю, что это самый простой способ:

drop((['A','B'],axis=1)

Ответ 16

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

Если вы пришли сюда в поисках информации о том, как удалить столбец (с тем же именем) из списка DataFrames, то есть несколько способов сделать это.

Одним из методов является перебор списка и изменение каждого DataFrame на месте:

# In-place assignment
for df in df_list:
    df.drop('colname', axis=1, inplace=True)

Или же,

for df in df_list: df.pop('colname')

Либо удалите столбец (не на месте) и присвойте результат обратно этой позиции в списке.

# Reassigning a copy back to the list
for i, df in enumerate(df_list):
    df_list[i] = df.drop('colname', axis=1, inplace=True)

Воспроизводимый пример кода

df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [4, 5, 7], 'C': ['a', 'b', 'c']})

df1
   A  B
0  1  4
1  2  5
2  3  6

df2
   A  C
0  4  a
1  5  b
2  7  c

df_list = [df1, df2]

# Drop column "A"
for df in df_list:
    df.drop('A', axis=1, inplace=True)

df1
   B
0  4
1  5
2  6

df2
   C
0  a
1  b
2  c

Почему не работает for df in df_list: df = df.drop('colname', axis=1) (т. for df in df_list: df = df.drop('colname', axis=1) Переназначение внутри цикла)?

Как упоминалось в других ответах, df.drop возвращает копию по умолчанию. Копия возвращается и переназначается переменной df без каких-либо изменений в оригинале. Вам нужно будет либо изменить df на месте с помощью аргумента inplace=True, либо явно переназначить копию этому элементу списка.

Заметка
Важно понимать разницу между переменными и объектами. Переменные содержат ссылки на объекты. Переменные могут быть переназначены для ссылки на разные объекты, это не имеет ничего общего с изменением самого объекта. Для хорошего изучения этой темы я рекомендую прочитать эту статью Неда Батчелдера.

Ответ 17

Вы также можете сначала установить все значения colum в NaN и затем сбросить значения NaN с помощью dropna()

df["column"]=np.NaN
df.dropna(axis=1,inplace=True)

Ответ 18

Еще один способ удаления столбца в Pandas DataFrame

если вы не ищете удаление на месте, то вы можете создать новый DataFrame, указав столбцы, используя DataFrame(...) как

my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']}

df = pd.DataFrame(my_dict)

Создайте новый DataFrame как

newdf = pd.DataFrame(df, columns=['name', 'age'])

Вы получаете такой же хороший результат, как и результат del/drop.

Ответ 19

Используйте drop для удаления столбца:

dataframe = dataframe.drop('column_name', 1) # 0 for rows and 1 for columns

Чтобы удалить столбец без переназначения:

dataframe.drop('column_name', axis=1, inplace=True)

Ответ 20

Вы можете сделать это 2 ways.

  1. del df['column_name']
  2. df.drop(columns=['column_name], axis=1, inplace=True)

счастливого обучения.