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.