Удалить столбец из панды 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".
Архитектурные вопросы, стоящие за этой проблемой
- Является ли датафрейм коллекцией столбцов?
- Является ли датафрейм набором строк?
- Является ли столбец атрибутом кадра данных?
Панда отвечает:
- Да, во всех отношениях
- Нет, но если вы хотите, чтобы это было, вы можете использовать
.ix
, .loc
или .iloc
. - Может быть, вы хотите прочитать данные? Тогда да, если только имя атрибута не занято другим атрибутом, принадлежащим фрейму данных. Вы хотите изменить данные? Тогда нет.
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()]
Что все оценивают по:
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.
-
del df['column_name']
-
df.drop(columns=['column_name], axis=1, inplace=True)
счастливого обучения.