от пандDataFrame
Удаление одного или нескольких столбцов — довольно распространенная задача, но оказывается, что существует множество возможных способов выполнения этой задачи. я нашелЭтот вопрос StackOverflow, а решения и обсуждения в них поднимают много интересных тем. Стоит углубиться в детали.
Во-первых, изDataFrame
Каков «правильный» способ удаления столбца в ? Стандартный способ — думать на языке SQL и использоватьdrop
.
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(25).reshape((5,5)), columns=list("abcde"))
display(df)
try:
df.drop('b')
except KeyError as ke:
print(ke)
a b c d e
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
"['b'] not found in axis"
Чего ждать? Почему я получаю сообщение об ошибке? Это потому чтоdrop
Ось работы по умолчанию — линии. Как и многие методы pandas, этот метод можно вызвать несколькими способами (некоторых это расстраивает).
ты можешь использоватьaxis=0
илиaxis='rows'
удалите строку или используйтеlabels
параметр.
df.drop(0) # drop a row, on axis 0 or 'rows'
df.drop(0, axis=0) # same
df.drop(0, axis='rows') # same
df.drop(labels=0) # same
df.drop(labels=[0]) # same
a b c d e
1 5 6 7 8 9
2 10 11 12 13 14
3 15 16 17 18 19
4 20 21 22 23 24
Опять же, как мы удаляем столбец?
Мы хотим удалить столбец, так как это выглядит? вы можете указатьaxis
или используйтеcolumns
параметр.
df.drop('b', axis=1) # drop a column
df.drop('b', axis='columns') # same
df.drop(columns='b') # same
df.drop(columns=['b']) # same
a c d e
0 0 2 3 4
1 5 7 8 9
2 10 12 13 14
3 15 17 18 19
4 20 22 23 24
Ну, вот как вы опускаете столбец. Теперь вам нужно присвоить его новой переменной, либо вернуться к старой переменной, либо передатьinplace=True
, чтобы сделать изменение постоянным.
df2 = df.drop('b', axis=1)
print(df2.columns)
print(df.columns)
Index(['a', 'c', 'd', 'e'], dtype='object')
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
Стоит отметить, что при использовании обоихindex
иcolumns
параметр, вы можете использовать drop, чтобы удалить как строки, так и столбцы, и вы можете передать несколько значений.
df.drop(index=[0,2], columns=['b','c'])
a d e
1 5 8 9
3 15 18 19
4 20 23 24
Если у вас нет метода перетаскивания, вы можете получить тот же результат с помощью индексации. Есть много способов выполнить эту задачу, но эквивалентным решением является использование.loc
индексатор иisin
, инвертируя выделение.
df.loc[~df.index.isin([0,2]), ~df.columns.isin(['b', 'c'])]
a d e
1 5 8 9
3 15 18 19
4 20 23 24
Если для вас ничего из этого не имеет смысла, я предлагаю вам прочитать мою серию о выборе и индексировании в пандах, начиная сздесьНачинать.
вернуться к вопросу
Возвращаясь к исходному вопросу, мы видим, что существует еще один способ удаления столбца.
del df['a']
df
b c d e
0 1 2 3 4
1 6 7 8 9
2 11 12 13 14
3 16 17 18 19
4 21 22 23 24
Пуф, оно просто исчезло. Это как использоватьinplace=True
удалить.
Как насчет доступа к собственности?
Мы также знаем, что можем использовать атрибут доступа к _select_DataFrame
столбец.
df.b
0 1
1 6
2 11
3 16
4 21
Name: b, dtype: int64
Можем ли мы удалить столбцы таким образом?
del df.b
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-10-0dca358a6ef9> in <module>
----> 1 del df.b
AttributeError: b
мы не можем. В текущем дизайне панд нельзя удалять столбцы. Это технически невозможно? Почемуdel df['b']
Да, покаdel df.b
Но это не работает? Давайте углубимся в эти детали и посмотрим, можно ли заставить работать и вторую версию.
Первая версия работает, потому что в пандахDataFrame
Достигнуто__delitem__
метод, когда вы выполняетеdel df['b']
будет вызвано, когда . но,del df.b
, есть ли способ справиться с этой проблемой?
Во-первых, давайте создадим простой класс, чтобы показать, как этот класс работает внутри. мы не делаем настоящегоDataFrame
, но просто используйтеdict
, как контейнер для нашего столбца (он действительно может содержать что угодно, мы не делаем здесь никакого индексирования).
class StupidFrame:
def __init__(self, columns):
self.columns = columns
def __delitem__(self, item):
del self.columns[item]
def __getitem__(self, item):
return self.columns[item]
def __setitem__(self, item, val):
self.columns[item] = val
f = StupidFrame({'a': 1, 'b': 2, 'c': 3})
print("StupidFrame value for a:", f['a'])
print("StupidFrame columns: ", f.columns)
del f['b']
f.d = 4
print("StupidFrame columns: ", f.columns)
StupidFrame value for a: 1
StupidFrame columns: {'a': 1, 'b': 2, 'c': 3}
StupidFrame columns: {'a': 1, 'c': 3}
Здесь следует отметить несколько вещей. Во-первых, мы можем использовать оператор индекса ([]
) посетите нашStupidFrame
и используйте его для установки, получения и удаления элементов. когда мы ставимd
Когда он был назначен нашему фрейму, он не был добавлен в наш столбец, потому что это просто обычное свойство экземпляра. Если мы хотим иметь возможность обрабатывать столбцы как свойства, нам нужно проделать больше работы.
Итак, следуя примеру pandas (который поддерживает доступ к атрибутам для столбцов), мы добавляем__getattr__
метод, но мы также будем использовать__setattr__
Метод обрабатывает настройку и делает вид, что любое присвоение свойства является «столбцом». Мы должны обновить наш словарь экземпляров напрямую (__dict__
), чтобы избежать бесконечной рекурсии.
class StupidFrameAttr:
def __init__(self, columns):
self.__dict__['columns'] = columns
def __delitem__(self, item):
del self.__dict__['columns'][item]
def __getitem__(self, item):
return self.__dict__['columns'][item]
def __setitem__(self, item, val):
self.__dict__['columns'][item] = val
def __getattr__(self, item):
if item in self.__dict__['columns']:
return self.__dict__['columns'][item]
elif item == 'columns':
return self.__dict__[item]
else:
raise AttributeError
def __setattr__(self, item, val):
if item != 'columns':
self.__dict__['columns'][item] = val
else:
raise ValueError("Overwriting columns prohibited")
f = StupidFrameAttr({'a': 1, 'b': 2, 'c': 3})
print("StupidFrameAttr value for a", f['a'])
print("StupidFrameAttr columns: ", f.columns)
del f['b']
print("StupidFrameAttr columns: ", f.columns)
print("StupidFrameAttr value for a", f.a)
f.d = 4
print("StupidFrameAttr columns: ", f.columns)
del f['d']
print("StupidFrameAttr columns: ", f.columns)
f.d = 5
print("StupidFrameAttr columns: ", f.columns)
del f.d
StupidFrameAttr value for a 1
StupidFrameAttr columns: {'a': 1, 'b': 2, 'c': 3}
StupidFrameAttr columns: {'a': 1, 'c': 3}
StupidFrameAttr value for a 1
StupidFrameAttr columns: {'a': 1, 'c': 3, 'd': 4}
StupidFrameAttr columns: {'a': 1, 'c': 3}
StupidFrameAttr columns: {'a': 1, 'c': 3, 'd': 5}
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-12-fd29f59ea01e> in <module>
39 f.d = 5
40 print("StupidFrameAttr columns: ", f.columns)
---> 41 del f.d
AttributeError: d
Как мы можем справиться с удалением?
Все работает, кроме удаления с использованием доступа к свойствам. Мы используем оператор индекса массива ([]
) и доступ к свойствам для настройки/получения столбцов. Но как обнаружить удаление? Это возможно?
Один из способов - использовать__delattr__
метод, которыймодель данныхОписано в документации. Если вы определите этот метод в своем классе, он будет вызываться вместо прямого обновления словаря свойств экземпляра. Это дает нам возможность перенаправить его в экземпляр нашего столбца.
class StupidFrameDelAttr(StupidFrameAttr):
def __delattr__(self, item):
# trivial implementation using the data model methods
del self.__dict__['columns'][item]
f = StupidFrameDelAttr({'a': 1, 'b': 2, 'c': 3})
print("StupidFrameDelAttr value for a", f['a'])
print("StupidFrameDelAttr columns: ", f.columns)
del f['b']
print("StupidFrameDelAttr columns: ", f.columns)
print("StupidFrameDelAttr value for a", f.a)
f.d = 4
print("StupidFrameDelAttr columns: ", f.columns)
del f.d
print("StupidFrameDelAttr columns: ", f.columns)
StupidFrameDelAttr value for a 1
StupidFrameDelAttr columns: {'a': 1, 'b': 2, 'c': 3}
StupidFrameDelAttr columns: {'a': 1, 'c': 3}
StupidFrameDelAttr value for a 1
StupidFrameDelAttr columns: {'a': 1, 'c': 3, 'd': 4}
StupidFrameDelAttr columns: {'a': 1, 'c': 3}
Теперь я не говорю, что удаление атрибутов столбцов легко добавить в pandas, но, по крайней мере, это показывает, что это возможно. В текущих пандах лучше всего использовать удаление столбцаdrop
.
Кроме того, здесь стоит упомянуть, что когда вы создаете новый столбец в pandas, вы не назначаете его атрибутом. Чтобы лучше понять, как правильно создать столбец, вы можете посмотретьэта статья.
Если вы уже знаете, как сбросить столбец в pandas, надеюсь, вы узнали немного больше о работе.
The postHow to remove a column from a DataFrame, with some extra detailappeared first onwrighters.io.