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?

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

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

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.


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

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)

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

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)


2

Jangan jatuh. Tangkap kebalikan dari apa yang Anda inginkan.

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

1

cara terpendek untuk melakukannya adalah:

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

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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.