Letakkan kolom yang namanya berisi string tertentu dari pandas DataFrame

106

Saya memiliki kerangka data panda dengan nama kolom berikut:

Result1, Test1, Result2, Test2, Result3, Test3, dll ...

Saya ingin membuang semua kolom yang namanya mengandung kata "Test". Jumlah kolom tersebut tidak statis tetapi bergantung pada fungsi sebelumnya.

Bagaimana saya bisa melakukan itu?

Alexis Eggermont
sumber

Jawaban:

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
Nic
sumber
2
OP tidak menentukan bahwa penghapusan harus case insensitive.
Phillip Cloud
163

Inilah cara yang bagus untuk ini:

df = df[df.columns.drop(list(df.filter(regex='Test')))]
Bindiya 12
sumber
47
Atau langsung di tempat:df.drop(list(df.filter(regex = 'Test')), axis = 1, inplace = True)
Axel
7
Ini adalah solusi yang jauh lebih elegan daripada jawaban yang diterima. Saya akan memecahnya sedikit lebih banyak untuk menunjukkan alasannya, terutama mengekstraksi list(df.filter(regex='Test'))untuk lebih menunjukkan apa yang dilakukan garis. Saya juga akan memilih df.filter(regex='Test').columnslebih dari konversi daftar
Charles
2
Yang ini jauh lebih elegan daripada jawaban yang diterima.
deepelement
4
Saya benar-benar bertanya-tanya apa arti komentar yang mengatakan jawaban ini "elegan". Saya sendiri merasa cukup dikaburkan, ketika kode python harus dapat dibaca terlebih dahulu. Ini juga dua kali lebih lambat dari jawaban pertama. Dan itu menggunakan regexkata kunci saat likekata kunci tampaknya lebih memadai.
Jacquot
2
Ini sebenarnya bukan jawaban yang bagus seperti yang diklaim orang. Masalahnya filteradalah ia mengembalikan salinan SEMUA data sebagai kolom yang ingin Anda jatuhkan. Akan sia-sia jika Anda hanya meneruskan hasil ini ke drop(yang lagi-lagi mengembalikan salinan) ... solusi yang lebih baik adalah str.startswith(saya telah menambahkan jawaban dengan itu di sini).
cs95
41

Lebih Murah, Lebih Cepat, dan Idiomatis: str.contains

Di versi terbaru panda, Anda dapat menggunakan metode string pada indeks dan kolom. Di sini, str.startswithsepertinya cocok.

Untuk menghapus semua kolom yang dimulai dengan substring tertentu:

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

Untuk pencocokan tidak peka huruf besar / kecil, Anda dapat menggunakan pencocokan berbasis ekspresi reguler dengan str.containsdengan anchor 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

jika tipe campuran adalah suatu kemungkinan, sebutkan na=Falsejuga.

cs95
sumber
15

Anda dapat memfilter kolom yang Anda inginkan menggunakan 'filter'

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

Sekarang saring

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

Dapatkan..

   result1  result34
0   2.0     NaN
1   NaN     10.0
SAH
sumber
4
Jawaban Terbaik! Terima kasih. Bagaimana Anda memfilter sebaliknya? not like='result'
stallingOne
2
lalu lakukan ini: df = df.drop (df.filter (like = 'result', axis = 1) .columns, axis = 1)
Amir
14

Ini bisa dilakukan dengan rapi dalam satu baris dengan:

df = df.drop(df.filter(regex='Test').columns, axis=1)
Warren O'Neill
sumber
1
Demikian pula (dan lebih cepat):df.drop(df.filter(regex='Test').columns, axis=1, inplace=True)
Max Ghenis
9

Gunakan DataFrame.selectmetode:

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
Phillip Cloud
sumber
Dan op tidak menentukan bahwa sebuah nomor harus mengikuti 'Test': Saya ingin menghapus semua kolom yang namanya mengandung kata "Test" .
7stud
Asumsi bahwa suatu angka mengikuti Tes sangat masuk akal. Baca ulang pertanyaannya.
Phillip Cloud
2
sekarang melihat:FutureWarning: 'select' is deprecated and will be removed in a future release. You can use .loc[labels.map(crit)] as a replacement
flutefreak7
Ingatlah untuk import resebelumnya.
ijoseph
5

Metode ini melakukan segalanya pada tempatnya. Banyak dari jawaban lain membuat salinan dan tidak seefisien:

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

ba0101
sumber
2

Jangan jatuh. Tangkap kebalikan dari apa yang Anda inginkan.

df = df.filter(regex='^((?!badword).)*$').columns
Roy Assis
sumber
1

cara terpendek untuk melakukannya adalah:

resdf = df.filter(like='Test',axis=1)
ZacNt
sumber
Ini sudah tercakup dalam jawaban ini .
Gino Mempin
1
Meskipun jawaban yang ditautkan dalam komentar di atas serupa, itu tidak sama. Nyatanya, justru sebaliknya.
Makyen
0

Solusi saat menjatuhkan daftar nama kolom yang berisi regex. Saya lebih suka pendekatan ini karena saya sering mengedit daftar drop-list. Menggunakan regex filter negatif untuk daftar drop.

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)
BSalita
sumber