Solte as colunas cujo nome contém uma string específica do pandas DataFrame


106

Eu tenho um dataframe do pandas com os seguintes nomes de coluna:

Resultado1, Teste1, Resultado2, Teste2, Resultado3, Teste3, etc ...

Desejo eliminar todas as colunas cujo nome contém a palavra "Teste". O número dessas colunas não é estático, mas depende de uma função anterior.

Como eu posso fazer isso?

Respostas:


74
import pandas as pd

import numpy as np

array=np.random.random((2,4))

df=pd.DataFrame(array, columns=('Test1', 'toto', 'test2', 'riri'))

print df

      Test1      toto     test2      riri
0  0.923249  0.572528  0.845464  0.144891
1  0.020438  0.332540  0.144455  0.741412

cols = [c for c in df.columns if c.lower()[:4] != 'test']

df=df[cols]

print df
       toto      riri
0  0.572528  0.144891
1  0.332540  0.741412

2
O OP não especificou que a remoção não diferencia maiúsculas de minúsculas.
Phillip Cloud

163

Esta é uma boa maneira de fazer isso:

df = df[df.columns.drop(list(df.filter(regex='Test')))]

47
Ou diretamente no local:df.drop(list(df.filter(regex = 'Test')), axis = 1, inplace = True)
Axel de

7
Esta é uma solução muito mais elegante do que a resposta aceita. Eu dividiria um pouco mais para mostrar o porquê, principalmente extraindo list(df.filter(regex='Test'))para mostrar melhor o que a linha está fazendo. Eu também optaria pela df.filter(regex='Test').columnsconversão de lista
Charles,

2
Esta é muito mais elegante do que a resposta aceita.
deepelement

4
Eu realmente me pergunto o que significam os comentários que dizem que essa resposta é "elegante". Eu mesmo acho isso bastante ofuscado, quando o código python deveria ser lido pela primeira vez. Também é duas vezes mais lento do que a primeira resposta. E ele usa a regexpalavra - chave quando a likepalavra - chave parece ser mais adequada.
Jacquot

2
Esta não é uma resposta tão boa quanto as pessoas afirmam. O problema filteré que ele retorna uma cópia de TODOS os dados como colunas que você deseja eliminar. É um desperdício se você estiver apenas passando esse resultado para drop(que novamente retorna uma cópia) ... uma solução melhor seria str.startswith(adicionei uma resposta com isso aqui).
cs95

41

Mais barato, mais rápido e idiomático: str.contains

Em versões recentes do pandas, você pode usar métodos de string no índice e nas colunas. Aqui, str.startswithparece um bom ajuste.

Para remover todas as colunas começando com uma determinada substring:

df.columns.str.startswith('Test')
# array([ True, False, False, False])

df.loc[:,~df.columns.str.startswith('Test')]

  toto test2 riri
0    x     x    x
1    x     x    x

Para correspondência que não diferencia maiúsculas de minúsculas, você pode usar a correspondência baseada em regex str.containscom uma âncora SOL:

df.columns.str.contains('^test', case=False)
# array([ True, False,  True, False])

df.loc[:,~df.columns.str.contains('^test', case=False)] 

  toto riri
0    x    x
1    x    x

se os tipos mistos forem uma possibilidade, especifique na=Falsetambém.


15

Você pode filtrar as colunas que deseja usando 'filtro'

import pandas as pd
import numpy as np

data2 = [{'test2': 1, 'result1': 2}, {'test': 5, 'result34': 10, 'c': 20}]

df = pd.DataFrame(data2)

df

    c   result1     result34    test    test2
0   NaN     2.0     NaN     NaN     1.0
1   20.0    NaN     10.0    5.0     NaN

Agora filtrar

df.filter(like='result',axis=1)

Obter..

   result1  result34
0   2.0     NaN
1   NaN     10.0

4
Melhor resposta! Obrigado. Como você filtra o oposto? not like='result'
stallingOne

2
então faça isto: df = df.drop (df.filter (like = 'resultado', eixo = 1) .colunas, eixo = 1)
Amir

14

Isso pode ser feito perfeitamente em uma linha com:

df = df.drop(df.filter(regex='Test').columns, axis=1)

1
Da mesma forma (e mais rápido):df.drop(df.filter(regex='Test').columns, axis=1, inplace=True)
Max Ghenis

9

Use o DataFrame.selectmétodo:

In [38]: df = DataFrame({'Test1': randn(10), 'Test2': randn(10), 'awesome': randn(10)})

In [39]: df.select(lambda x: not re.search('Test\d+', x), axis=1)
Out[39]:
   awesome
0    1.215
1    1.247
2    0.142
3    0.169
4    0.137
5   -0.971
6    0.736
7    0.214
8    0.111
9   -0.214

E a op não especificou que um número deve seguir 'Teste': Eu quero descartar todas as colunas cujo nome contém a palavra "Teste" .
7 de

A suposição de que um número segue Test é perfeitamente razoável. Releia a pergunta.
Phillip Cloud

2
vendo agora:FutureWarning: 'select' is deprecated and will be removed in a future release. You can use .loc[labels.map(crit)] as a replacement
flutefreak7

Lembre-se de import reantes.
ijoseph

5

Este método faz tudo no local. Muitas das outras respostas criam cópias e não são tão eficientes:

df.drop(df.columns[df.columns.str.contains('Test')], axis=1, inplace=True)


2

Não deixe cair. Pegue o oposto do que você deseja.

df = df.filter(regex='^((?!badword).)*$').columns

1

a maneira mais curta de fazer é:

resdf = df.filter(like='Test',axis=1)

Isso já foi coberto por esta resposta .
Gino Mempin

1
Embora a resposta vinculada no comentário acima seja semelhante, não é a mesma. Na verdade, é quase o oposto.
Makyen

0

Solução ao eliminar uma lista de nomes de colunas contendo regex. Prefiro essa abordagem porque frequentemente edito a lista suspensa. Usa um regex de filtro negativo para a lista suspensa.

drop_column_names = ['A','B.+','C.*']
drop_columns_regex = '^(?!(?:'+'|'.join(drop_column_names)+')$)'
print('Dropping columns:',', '.join([c for c in df.columns if re.search(drop_columns_regex,c)]))
df = df.filter(regex=drop_columns_regex,axis=1)
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.