Thả các cột có tên chứa một chuỗi cụ thể từ DataFrame của gấu trúc


105

Tôi có khung dữ liệu gấu trúc với các tên cột sau:

Kết quả1, Thử nghiệm1, Kết quả2, Thử nghiệm2, Kết quả3, Thử nghiệm3, v.v.

Tôi muốn bỏ tất cả các cột có tên chứa từ "Kiểm tra". Số lượng các cột như vậy không phải là tĩnh mà phụ thuộc vào một hàm trước đó.

Làm thế nào tôi có thể làm điều đó?

Câu trả lời:


73
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 không chỉ định rằng việc xóa phải phân biệt chữ hoa chữ thường.
Phillip Cloud

162

Đây là một cách tốt để làm điều này:

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

47
Hoặc trực tiếp tại chỗ:df.drop(list(df.filter(regex = 'Test')), axis = 1, inplace = True)
Axel

7
Đây là một giải pháp thanh lịch hơn nhiều so với câu trả lời được chấp nhận. Tôi sẽ chia nhỏ hơn một chút để giải thích tại sao, chủ yếu là trích xuất list(df.filter(regex='Test'))để hiển thị tốt hơn những gì dòng đang làm. Tôi cũng sẽ chọn df.filter(regex='Test').columnschuyển đổi qua danh sách
Charles

2
Đây là cách thanh lịch hơn câu trả lời được chấp nhận.
deepelement

4
Tôi thực sự tự hỏi những ý kiến ​​nói rằng câu trả lời này là "thanh lịch" nghĩa là gì. Bản thân tôi thấy nó khá khó hiểu, khi mã python trước tiên phải có thể đọc được. Nó cũng chậm hơn hai lần so với câu trả lời đầu tiên. Và nó sử dụng regextừ khóa khi liketừ khóa có vẻ phù hợp hơn.
Jacquot

2
Đây thực sự không phải là một câu trả lời tốt như mọi người vẫn khẳng định. Vấn đề filterlà nó trả về một bản sao của TẤT CẢ dữ liệu dưới dạng cột mà bạn muốn bỏ. Thật lãng phí nếu bạn chỉ chuyển kết quả này tới drop( kết quả này lại trả về một bản sao) ... một giải pháp tốt hơn sẽ là str.startswith(Tôi đã thêm một câu trả lời với điều đó ở đây).
cs95,

40

Rẻ hơn, nhanh hơn và Idiomatic: str.contains

Trong các phiên bản gần đây của gấu trúc, bạn có thể sử dụng phương thức chuỗi trên chỉ mục và cột. Đây, str.startswithcó vẻ như là một sự phù hợp tốt.

Để xóa tất cả các cột bắt đầu bằng một chuỗi con nhất định:

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

Đối với đối sánh không phân biệt chữ hoa chữ thường, bạn có thể sử dụng đối sánh dựa trên regex str.containsvới neo 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

nếu các loại hỗn hợp là một khả năng, hãy chỉ rõ na=False.


15

Bạn có thể lọc ra các cột bạn muốn bằng cách sử dụng 'bộ lọc'

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

Bây giờ lọc

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

Được..

   result1  result34
0   2.0     NaN
1   NaN     10.0

4
Câu trả lời tốt nhất! Cảm ơn. Làm thế nào để bạn lọc ngược lại? not like='result'
ngừng trệMột

2
sau đó làm điều này: df = df.drop (df.filter (như = 'kết quả', axis = 1) .columns, axis = 1)
Amir

14

Điều này có thể được thực hiện gọn gàng trong một dòng với:

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

1
Tương tự (và nhanh hơn):df.drop(df.filter(regex='Test').columns, axis=1, inplace=True)
Max Ghenis

9

Sử dụng DataFrame.selectphương pháp:

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

Và op không chỉ định rằng một số phải tuân theo 'Kiểm tra': Tôi muốn loại bỏ tất cả các cột có tên chứa từ "Kiểm tra" .
7stud

Giả định rằng một số theo sau Phép thử là hoàn toàn hợp lý. Đọc lại câu hỏi.
Phillip Cloud

2
bây giờ đang nhìn thấy:FutureWarning: 'select' is deprecated and will be removed in a future release. You can use .loc[labels.map(crit)] as a replacement
sáofreak7 Ngày

Hãy nhớ import retrước.
ijoseph

5

Phương pháp này thực hiện mọi thứ tại chỗ. Nhiều câu trả lời khác tạo ra các bản sao và không hiệu quả:

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


2

Đừng làm rơi. Nắm bắt điều ngược lại với những gì bạn muốn.

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

1

cách ngắn nhất để làm là:

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

Điều này đã được bao phủ bởi câu trả lời này .
Gino Mempin

1
Mặc dù câu trả lời được liên kết trong nhận xét trên là tương tự, nhưng nó không giống nhau. Trong thực tế, nó gần như ngược lại.
Makyen

0

Giải pháp khi bỏ danh sách tên cột chứa regex. Tôi thích cách tiếp cận này hơn vì tôi thường xuyên chỉnh sửa danh sách thả. Sử dụng regex bộ lọc phủ định cho danh sách thả.

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.