Excluir coluna do pandas DataFrame


1331

Ao excluir uma coluna em um DataFrame, eu uso:

del df['column_name']

E isso funciona muito bem. Por que não consigo usar o seguinte?

del df.column_name

Como é possível acessar a coluna / série como df.column_name, eu esperava que isso funcionasse.


2
Observe que esta questão está sendo discutida no Meta .
RM

Respostas:


860

Como você adivinhou, a sintaxe correta é

del df['column_name']

É difícil fazer o del df.column_nametrabalho simplesmente como resultado de limitações sintáticas no Python. del df[name]é traduzido para o df.__delitem__(name)abrigo por Python.


25
Sei que essa é uma "resposta" super antiga, mas minha curiosidade é aguçada - por que isso é uma limitação sintática do Python? class A(object): def __init__(self): self.var = 1configura uma classe e depois a = A(); del a.varfunciona muito bem ...
dwanderson 4/16

14
@dwanderson a diferença é que, quando uma coluna deve ser removida, o DataFrame precisa ter seu próprio tratamento para "como fazê-lo". No caso de del df[name], é traduzido para df.__delitem__(name)qual é um método que o DataFrame pode implementar e modificar de acordo com suas necessidades. No caso de del df.name, a variável membro é removida sem chance de execução de qualquer código personalizado. Considere o seu próprio exemplo - você pode del a.varresultar em uma impressão de "exclusão de variável"? Se puder, por favor me diga como. Eu não posso :)
Yonatan


5
O comentário de @Yonatan Eugene também se aplica ao Python 2; descritores foram em Python 2 desde 2.2 e é trivial para satisfazer sua exigência;)
CS

1
Esta resposta não está realmente correta - os pandasdesenvolvedores não , mas isso não significa que é difícil de fazer.
Wizzwizz4

2186

A melhor maneira de fazer isso nos pandas é usar drop:

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

onde 1é o número do eixo ( 0para linhas e 1colunas).

Para excluir a coluna sem precisar reatribuir, dfvocê pode:

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

Finalmente, para soltar pelo número da coluna em vez do rótulo da coluna , tente excluir, por exemplo, a 1ª, a 2ª e a 4ª colunas:

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

Também trabalhando com a sintaxe "texto" para as colunas:

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

79
Isso é recomendado por delalgum motivo?
beardc

20
Embora esse método de exclusão tenha seus méritos, essa resposta realmente não responde à pergunta que está sendo feita.
Paul

109
Verdadeiro @Paul, mas devido ao título da pergunta, a maioria das pessoas que chega aqui o faz tentando descobrir como excluir uma coluna.
LondonRob

24
@beardc outra vantagem de dropmais delé quedrop permite soltar várias colunas de uma só vez, realizar o inplace operação ou não, e também registos de exclusão ao longo de qualquer eixo (especialmente útil para uma matriz de 3-D ou Panel)
HOBs

8
Outra vantagem do dropover delé que o drop faz parte da API do pandas e contém documentação.
modulitos

242

Usar:

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

Isso excluirá uma ou mais colunas no local. Observe que inplace=Truefoi adicionado no pandas v0.13 e não funcionará em versões mais antigas. Você teria que atribuir o resultado novamente nesse caso:

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

3
Uma observação sobre esta resposta: se uma 'lista' for usada, os colchetes devem ser removidos:df.drop(list,inplace=True,axis=1)
edesz

1
essa deve ser realmente a resposta aceita, porque deixa clara a superioridade desse método del- pode deixar cair mais de uma coluna ao mesmo tempo.
dbliss

111

Drop por índice

Exclua primeira, segunda e quarta colunas:

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

Exclua a primeira coluna:

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

Existe um parâmetro opcional inplace para que os dados originais possam ser modificados sem criar uma cópia.

Popped

Seleção, adição e exclusão de colunas

Excluir coluna column-name:

df.pop('column-name')

Exemplos:

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
Como faço para aparecer uma linha em pandas?
Kennet Celeste

2
@Yugi Você pode usar um quadro de dados transposto para isso. ex - df.T.pop('A')
Clock Slave

@ClockSlave Isso não modifica o original df. Você poderia fazer, df = df.T; df.pop(index); df = df.Tmas isso parece excessivo.
cs95 23/05/19

Em vez de df.drop(df.columns[[0]], axis=1, inplace=True)não seria suficiente usar df.drop([0], axis=1)?
Anirban Mukherjee 04/04/19

1
@Anirban Mukherjee Depende. Se quiser excluir o nome da coluna 0, df.drop(0, axis=1)funcione bem. Mas se você não sabe o nome da coluna e precisa remover a primeira coluna df.drop(df.columns[[0]], axis=1, inplace=True), selecione a primeira coluna por posição e solte-a.
precisa saber é

71

A pergunta real colocada, perdida pela maioria das respostas aqui é:

Por que não posso usar del df.column_name ?

A princípio, precisamos entender o problema, o que exige que mergulhemos nos métodos mágicos do python .

Como Wes aponta em sua resposta, del df['column']mapeia o método mágico python df.__delitem__('column')que é implementado nos pandas para soltar a coluna

No entanto, conforme apontado no link acima sobre métodos mágicos python :

De fato, __del__quase nunca deve ser usado por causa das circunstâncias precárias sob as quais é chamado; use-o com cuidado!

Você pode argumentar que del df['column_name']não deve ser usado ou incentivado e, portanto del df.column_name, nem deve ser considerado.

Contudo, em teoria, del df.column_namepoderia ser implementado para trabalhar em pandas usando o método mágico__delattr__ . No entanto, isso introduz certos problemas, problemas que adel df['column_name']implementação já possui, mas em menor grau.

Problema de exemplo

E se eu definir uma coluna em um dataframe chamado "dtypes" ou "columns".

Então suponha que eu queira excluir essas colunas.

del df.dtypes faria o __delattr__confundiria método como se fosse excluir o atributo "dtypes" ou a coluna "dtypes".

Questões arquitetônicas por trás desse problema

  1. Um dataframe é uma coleção de colunas ?
  2. Um quadro de dados é uma coleção de linhas ?
  3. Uma coluna é um atributo de um quadro de dados?

Pandas respostas:

  1. Sim, de todas as maneiras
  2. Não, mas se você quiser, pode usar o .ix, .locou.iloc métodos .
  3. Talvez você queira ler dados? Então sim , a menos que o nome do atributo já esteja sendo usado por outro atributo pertencente ao quadro de dados. Deseja modificar dados? Então não .

TLDR;

Você não pode fazer isso del df.column_nameporque os pandas têm uma arquitetura bastante desenvolvida que precisa ser reconsiderada para que esse tipo de dissonância cognitiva não ocorra aos seus usuários.

Protip:

Não use df.column_name, pode ser bonito, mas causa dissonância cognitiva

Citações de Zen of Python que se encaixam aqui:

Existem várias maneiras de excluir uma coluna.

Deve haver uma - e preferencialmente apenas uma - maneira óbvia de fazê-lo.

Às vezes, colunas são atributos, mas às vezes não.

Casos especiais não são especiais o suficiente para violar as regras.

Exclui del df.dtypeso atributo dtypes ou a coluna dtypes?

Diante da ambiguidade, recuse a tentação de adivinhar.


"De fato, __del__quase nunca deve ser usado por causa das circunstâncias precárias sob as quais é chamado; use-o com cautela!" é completamente irrelevante aqui, como é o método usado aqui __delattr__.
pppery

1
@ppperry você está citando falta. é o delsignificado interno, não o .__del__método da instância. O delembutido está mapeando para __delattr__e __delitem__que é o que eu estou construindo o meu argumento sobre. Então, talvez você queira reler o que eu escrevi.
23818 firelynx

1
__... __é interpretado como marcação em negrito por StackExchange
pppery

2
"Não use df.column_name, pode ser bonito, mas causa dissonância cognitiva" O que isso significa? Eu não sou psicólogo, então tenho que procurar isso para entender o que você quer dizer. Além disso, citar The Zen não faz sentido porque existem centenas de maneiras válidas de fazer a mesma coisa nos pandas.
cs95 23/05/19

58

Uma boa adição é a capacidade de descartar colunas apenas se elas existirem . Dessa forma, você pode cobrir mais casos de uso, e isso eliminará apenas as colunas existentes dos rótulos passados ​​para ele:

Basta adicionar erros = 'ignorar' , por exemplo:

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • Isso é novo a partir dos pandas 0.16.1 em diante. A documentação está aqui .

41

da versão 0.16.1 você pode fazer

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

3
E isso também suporta a eliminação de várias colunas, algumas das quais não precisam existir (ou seja, sem gerar erros errors= 'ignore') df.drop(['column_1','column_2'], axis=1 , inplace=True,errors= 'ignore'), se tal aplicativo for desejado!
múon

31

É uma boa prática usar sempre a []notação. Um motivo é que o atributo notation ( df.column_name) não funciona para índices numerados:

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

Pandas 0.21+ resposta

A versão 0.21 do Pandas mudou um droppouco o método para incluir os parâmetros indexe columnspara corresponder à assinatura dos métodos renamee reindex.

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

Pessoalmente, prefiro usar o axisparâmetro para denotar colunas ou índices, porque é o parâmetro de palavra-chave predominante usado em quase todos os métodos de pandas. Mas agora você tem algumas opções adicionais na versão 0.21.


1
df.drop (['coluna_a', 'coluna_c'], eixo = 1) | que está trabalhando para mim por agora
YouAreAwesome

21

No pandas 0.16.1+, você pode descartar colunas apenas se elas existirem, de acordo com a solução postada por @eiTanLaVi. Antes dessa versão, você pode obter o mesmo resultado através da compreensão de uma lista condicional:

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

Muito esforço para encontrar uma solução marginalmente mais eficiente. Difícil justificar a complexidade adicional, sacrificando a simplicidade dedf.drop(dlst, 1, errors='ignore')

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

Preâmbulo
Excluir uma coluna é semanticamente o mesmo que selecionar as outras colunas. Vou mostrar alguns métodos adicionais a serem considerados.

Também focarei na solução geral de excluir várias colunas de uma só vez e permitir a tentativa de excluir colunas que não estão presentes.

O uso dessas soluções é geral e também funcionará no caso simples.


Instalação
Considere a pd.DataFrame dflista e para excluirdlst

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']

O resultado deve se parecer com:

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

Como estou equiparando a exclusão de uma coluna à seleção das outras colunas, dividirei-a em dois tipos:

  1. Seleção de etiqueta
  2. Seleção booleana

Seleção de etiqueta

Começamos fabricando a lista / matriz de rótulos que representam as colunas que queremos manter e sem as colunas que queremos excluir.

  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']

Colunas dos rótulos
Para comparar o processo de seleção, assuma:

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

Então podemos avaliar

  1. df.loc[:, cols]
  2. df[cols]
  3. df.reindex(columns=cols)
  4. df.reindex_axis(cols, 1)

Quais todos avaliam para:

   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

Fatia booleana

Podemos construir uma matriz / lista de booleanos para fatiar

  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)

Colunas do Booleano
Para fins de comparação

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

Quais todos avaliam para:

   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

Tempo robusto

Funções

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)

Teste

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()

Isso é relativo ao tempo que leva para executar df.drop(dlst, 1, errors='ignore'). Parece que depois de todo esse esforço, apenas melhoramos o desempenho modestamente.

insira a descrição da imagem aqui

Se fato as melhores soluções usam reindexou reindex_axisno hack list(set(df.columns.values.tolist()).difference(dlst)). Um segundo próximo e ainda muito marginalmente melhor do que 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

A sintaxe do ponto funciona em JavaScript, mas não em Python.

  • Pitão: del df['column_name']
  • JavaScript: del df['column_name'] ou del df.column_name

2

Se o seu quadro de dados original dfnão for muito grande, você não terá restrições de memória e precisará manter apenas algumas colunas, poderá criar um novo quadro de dados apenas com as colunas de que precisa:

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

2

Podemos remover ou excluir uma coluna especificada ou colunas sprcified por drop () método .

Suponha df seja um quadro de dados.

Coluna a ser removida = column0

Código:

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

Para remover várias colunas col1, col2,. . . , coln, precisamos inserir todas as colunas que precisavam ser removidas em uma lista. Em seguida, remova-os pelo método drop ().

Código:

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

Espero que seja útil.


df = df.drop([col1, col2, . . . , coln], axis=1)isso não funciona se eu especificar um nome de variável no lugar de col1, col2 etc. Recebo a coluna de erro que não está no eixo quando está definitivamente presente. @Littin Você poderia ajudar?
RSM

1

Outra maneira de excluir uma coluna no Pandas DataFrame

se você não estiver procurando pela exclusão no local, poderá criar um novo DataFrame especificando as colunas usando a DataFrame(...)função como

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

df = pd.DataFrame(my_dict)

Crie um novo DataFrame como

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

Você obtém um resultado tão bom quanto o obtido com del / drop


1
Isso é tecnicamente correto, mas parece bobagem precisar listar todas as colunas a serem mantidas, em vez das apenas uma (ou poucas) colunas que você deseja excluir.
cs95 23/05/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.