Видалити стовпчик із панд DataFrame


1326

При видаленні стовпця в DataFrame я використовую:

del df['column_name']

І це чудово працює. Чому я не можу використовувати наступне?

del df.column_name

Оскільки можна отримати доступ до стовпця / серії df.column_name, я очікував, що це спрацює.


2
Зауважте, це питання обговорюється в Meta .
РМ

Відповіді:


858

Як ви здогадалися, правильний синтаксис

del df['column_name']

Важко зробити del df.column_nameроботу просто наслідком синтаксичних обмежень у Python. del df[name]перекладається df.__delitem__(name)під обкладинку Python.


25
Я усвідомлюю, що це надзвичайно стара "відповідь", але моя цікавість надихається - чому це синтаксичне обмеження Python? class A(object): def __init__(self): self.var = 1налаштовує клас, потім a = A(); del a.varпрацює чудово ...
dwanderson

13
@dwanderson різниця полягає в тому, що коли стовпчик потрібно видалити, DataFrame повинен мати власну обробку для "як це зробити". У випадку з del df[name]цим він перекладається на df.__delitem__(name)метод, який DataFrame може реалізовувати та змінювати для своїх потреб. У випадку з del df.nameзмінною члена видаляється без жодного шансу для будь-якого запущеного спеціального коду. Розглянемо власний приклад - чи можна отримати del a.varрезультат надрукування "видалення змінної"? Якщо можете, скажіть, будь ласка, як. Я не можу :)
Йонатан

8
@Yonatan Ви можете використовувати для цього або docs.python.org/3/reference/datamodel.html#object.__delattr__, або дескриптори: docs.python.org/3/howto/descriptor.html
Євген Пахомов

5
@Yonatan Євген також стосується Python 2; дескриптори є в Python 2 з 2.2, і це тривіально, щоб задовольнити вашу вимогу;)
CS

1
Ця відповідь насправді не правильна - pandasрозробники цього не зробили , але це не означає, що це важко зробити.
wizzwizz4

2182

Найкращий спосіб зробити це в пандах 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 

Також працює з "текстовим" синтаксисом для стовпців:

df.drop(['column_nameA', 'column_nameB'], axis=1, inplace=True)

79
Чи рекомендується це delчомусь?
борода

20
Хоча цей спосіб видалення має свої достоїнства, ця відповідь насправді не відповідає на задане питання.
Пол

109
Правда @Paul, але через назву питання, більшість людей, які приїжджають сюди, зроблять це, намагаючись розробити, як видалити стовпець.
LondonRob

24
@beardc Ще одна перевага dropнад delтим, що dropдозволяє опускати декілька стовпців одночасно, виконувати операцію на місці чи ні, а також видаляти записи вздовж будь-якої осі (особливо корисно для 3-D матриці або Panel)
варильні панелі

8
Ще одна перевага dropнад delтим, що drop є частиною API панди і містить документацію.
modulitos

240

Використання:

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

Це видалить один або кілька стовпців на місці. Зауважте, що inplace=Trueдодано в pandas v0.13 і не працюватиме у старих версіях. У такому випадку вам доведеться призначити результат:

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

3
Примітка про цю відповідь: якщо використовується "список", квадратні дужки слід df.drop(list,inplace=True,axis=1)
випасти

1
це дійсно має бути прийнятою відповіддю, оскільки це дає зрозуміти перевагу цього методу над del- може опустити більше одного стовпця одночасно.
dbliss

111

Падіння за індексом

Видалити перший, другий та четвертий стовпці:

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

1
Як я можу вискакувати рядок у пандах?
Кеннет Селесте

2
@Yugi Для цього можна використовувати транспонований кадр даних. ex - df.T.pop('A')
Clock Slave

@ClockSlave Це не змінює оригінал df. Ви могли б зробити , df = df.T; df.pop(index); df = df.Tале це , здається надмірним.
cs95

Замість цього df.drop(df.columns[[0]], axis=1, inplace=True)не буде достатньо використовувати df.drop([0], axis=1)?
Анірбан Мукерджі

1
@Anirban Mukherjee Це залежить. Якщо потрібно видалити ім'я стовпця0 , то df.drop(0, axis=1)добре працюйте. Але якщо ви не знаєте ім'я стовпця і вам потрібно видалити перший стовпець, то потрібно df.drop(df.columns[[0]], axis=1, inplace=True), він вибирає перший стовпець за позицією та опускає його.
jezrael

71

Актуальне поставлене питання, пропущене більшістю відповідей тут:

Чому я не можу використовувати del df.column_name?

Спочатку нам потрібно зрозуміти проблему, яка вимагає від нас занурення в магічні методи пітона .

Як вказує Уес у своїй відповіді, del df['column']відображає магічний метод пітона, df.__delitem__('column')який реалізується в пандах, щоб скинути стовпчик

Однак, як зазначено у посиланні вище про методи магічного пітона :

Насправді __del__його майже ніколи не слід застосовувати через невизначені обставини, за яких воно називається; використовуйте його обережно!

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

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

Приклад завдання

Що робити, якщо я визначаю стовпчик у кадрі даних, який називається "типи" або "стовпці".

Тоді припустимо, що я хочу видалити ці стовпці.

del df.dtypesзробить __delattr__метод заплутаним так, ніби він повинен видалити атрибут "dtypes" або "dtypes".

Архітектурні питання, що стоять за цією проблемою

  1. Є фрейм даних колекцією стовпців ?
  2. Є фрейм даних колекцією рядків ?
  3. Це атрибут стовпця фрейму даних?

Панди відповідає:

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

TLDR;

Ви не можете цього зробити, del df.column_nameтому що в пандах є досить дикоросла архітектура, яку потрібно переглянути, щоб подібний когнітивний дисонанс не траплявся у користувачів.

Підказка:

Не використовуйте df.column_name, це може бути досить, але це викликає когнітивний дисонанс

Дзен з Python цитати, які вміщуються тут:

Існує кілька способів видалення стовпця.

Повинно бути один - і бажано лише один - очевидний спосіб це зробити.

Стовпці іноді є атрибутами, але іноді ні.

Особливі випадки недостатньо спеціальні для порушення правил.

Чи del df.dtypesвидаляє атрибут dtypes або стовпчик dtypes?

В умовах неоднозначності відмовтеся від спокуси здогадатися.


"Насправді, __del__його майже ніколи не слід застосовувати через невизначені обставини, за яких він викликаний; використовуйте його обережно!" тут абсолютно не має значення, як і метод, який тут використовується __delattr__.
pppery

1
@ppperry ви пропускаєте цитування. це delвбудована , що є в виду, а НЕ .__del__метод примірника. delВбудована команда відображення на __delattr__і __delitem__що то , що я будую свій аргумент на. Тож, можливо, ви хочете перечитати те, що я написав.
firelynx

1
__... __потрапляє в інтерпретацію як смілива розмітка від StackExchange
pppery

2
"Не використовуйте df.column_name. Це може бути досить, але це викликає когнітивний дисонанс" Що це означає? Я не психолог, тому мені доводиться шукати це, щоб зрозуміти, що ти маєш на увазі. Також цитувати дзен безглуздо, оскільки існує сотні дійсних способів зробити те ж саме в пандах.
cs95

58

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

Просто додайте помилки = 'ігноруйте' , наприклад:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Це нове від панд 0,16.1 і далі. Документація тут .

41

з версії 0.16.1 ви можете це зробити

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

3
І це також підтримує скидання декількох стовпців, деякі з яких не повинні існувати (тобто без помилки підвищення errors= 'ignore') df.drop(['column_1','column_2'], axis=1 , inplace=True,errors= 'ignore'), якщо така програма бажана!
мюн

31

Добре застосовувати []позначення завжди . Однією з причин є те, що позначення атрибута ( 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

26

Панда 0,21+ відповідь

Pandas версії 0.21 dropтрохи змінив метод, включаючи indexі columnsпараметри, і параметри, щоб відповідати підпису renameі reindexметодів.

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

Особисто я вважаю за краще використовувати axisпараметр для позначення стовпців або індексів, оскільки це переважаючий параметр ключових слів, який використовується майже у всіх методах панд. Але тепер у вас є кілька додаткових варіантів у версії 0.21.


1
df.drop (['column_a', 'column_c'], вісь = 1) | вона працює для мене зараз
YouAreAwesome

21

У пандах 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)

14

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

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

  1. Вибір мітки
  2. Булевий вибір

Вибір мітки

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

  1. df.columns.difference(dlst)

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

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

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

    # does not preserve order
    ['E', 'D', 'B', 'F', 'G', 'A', 'C']
  5. [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]

Тоді ми можемо оцінити

  1. df.loc[:, cols]
  2. df[cols]
  3. df.reindex(columns=cols)
  4. 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

Булева скибочка

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

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

Стовпці з булевих
для порівняння

bools = [x not in dlst for x in df.columns.values.tolist()]
  1. 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

2

Синтаксис точок працює в JavaScript, але не в Python.

  • Пітон: del df['column_name']
  • JavaScript: del df['column_name'] або del df.column_name

2

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

new_df = df[['spam', 'sausage']]

2

Ми можемо видалити або видалити вказаний стовпчик або закріплені стовпці методом drop () .

Припустимо, df є фреймом даних.

Стовпець, який потрібно видалити = колонка0

Код:

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

Для видалення кількох стовпців col1, col2,. . . , coln, ми повинні вставити всі стовпці, які потрібно було видалити у списку. Потім видаліть їх методом drop ().

Код:

df = df.drop([col1, col2, . . . , coln], axis=1)

Я сподіваюся, що це буде корисно.


df = df.drop([col1, col2, . . . , coln], axis=1)це не працює, якщо я вказую ім'я змінної замість col1, col2 і т. д. Я отримую стовпець помилки не в осі, коли його обов'язково присутній. @Littin Ви можете допомогти?
РСМ

1

Ще один спосіб видалення стовпця в програмі 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


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