gấu trúc: cách tốt nhất để chọn tất cả các cột có tên bắt đầu bằng X


104

Tôi có một DataFrame:

import pandas as pd
import numpy as np

df = pd.DataFrame({'foo.aa': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
                   'foo.fighters': [0, 1, np.nan, 0, 0, 0],
                   'foo.bars': [0, 0, 0, 0, 0, 1],
                   'bar.baz': [5, 5, 6, 5, 5.6, 6.8],
                   'foo.fox': [2, 4, 1, 0, 0, 5],
                   'nas.foo': ['NA', 0, 1, 0, 0, 0],
                   'foo.manchu': ['NA', 0, 0, 0, 0, 0],})

Tôi muốn chọn các giá trị của 1 trong các cột bắt đầu bằng foo.. Có cách nào tốt hơn để làm điều đó ngoài:

df2 = df[(df['foo.aa'] == 1)|
(df['foo.fighters'] == 1)|
(df['foo.bars'] == 1)|
(df['foo.fox'] == 1)|
(df['foo.manchu'] == 1)
]

Một cái gì đó tương tự như viết một cái gì đó như:

df2= df[df.STARTS_WITH_FOO == 1]

Câu trả lời sẽ in ra một DataFrame như sau:

   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

[4 rows x 7 columns]

Câu trả lời:


151

Chỉ cần thực hiện hiểu danh sách để tạo các cột của bạn:

In [28]:

filter_col = [col for col in df if col.startswith('foo')]
filter_col
Out[28]:
['foo.aa', 'foo.bars', 'foo.fighters', 'foo.fox', 'foo.manchu']
In [29]:

df[filter_col]
Out[29]:
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

Một phương pháp khác là tạo một chuỗi từ các cột và sử dụng phương thức vectorised str startswith:

In [33]:

df[df.columns[pd.Series(df.columns).str.startswith('foo')]]
Out[33]:
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

Để đạt được những gì bạn muốn, bạn cần thêm những thứ sau để lọc các giá trị không đáp ứng ==1tiêu chí của bạn :

In [36]:

df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]]==1]
Out[36]:
   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      NaN       1       NaN           NaN      NaN        NaN     NaN
1      NaN     NaN       NaN             1      NaN        NaN     NaN
2      NaN     NaN       NaN           NaN        1        NaN     NaN
3      NaN     NaN       NaN           NaN      NaN        NaN     NaN
4      NaN     NaN       NaN           NaN      NaN        NaN     NaN
5      NaN     NaN         1           NaN      NaN        NaN     NaN

BIÊN TẬP

OK sau khi xem những gì bạn muốn, câu trả lời phức tạp là:

In [72]:

df.loc[df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]] == 1].dropna(how='all', axis=0).index]
Out[72]:
   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

66

Bây giờ các chỉ mục của gấu trúc hỗ trợ các hoạt động chuỗi, được cho là cách đơn giản và tốt nhất để chọn các cột bắt đầu bằng 'foo' chỉ là:

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

Ngoài ra, bạn có thể lọc các nhãn cột (hoặc hàng) với df.filter(). Để chỉ định một biểu thức chính quy để khớp với các tên bắt đầu bằng foo.:

>>> df.filter(regex=r'^foo\.', axis=1)
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
3     4.7         0             0        0          0
4     5.6         0             0        0          0
5     6.8         1             0        5          0

Để chỉ chọn các hàng bắt buộc (chứa a 1) và các cột, bạn có thể sử dụng loc, chọn các cột bằng filter(hoặc bất kỳ phương pháp nào khác) và các hàng bằng cách sử dụng any:

>>> df.loc[(df == 1).any(axis=1), df.filter(regex=r'^foo\.', axis=1).columns]
   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
5     6.8         1             0        5          0

7

Cách đơn giản nhất là sử dụng str trực tiếp trên tên cột, không cần pd.Series

df.loc[:,df.columns.str.startswith("foo")]


1

Dựa trên câu trả lời của @ EdChum, bạn có thể thử giải pháp sau:

df[df.columns[pd.Series(df.columns).str.contains("foo")]]

Điều này sẽ thực sự hữu ích trong trường hợp không phải tất cả các cột bạn muốn chọn đều bắt đầu bằng foo . Phương thức này chọn tất cả các cột có chứa chuỗi con foovà nó có thể được đặt vào bất kỳ điểm nào trong tên của cột.

Về bản chất, tôi thay thế .startswith()bằng .contains().


0

Giải pháp của tôi. Nó có thể chậm hơn về hiệu suất:

a = pd.concat(df[df[c] == 1] for c in df.columns if c.startswith('foo'))
a.sort_index()


   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

0

Một tùy chọn khác để lựa chọn các mục nhập mong muốn là sử dụng map:

df.loc[(df == 1).any(axis=1), df.columns.map(lambda x: x.startswith('foo'))]

cung cấp cho bạn tất cả các cột cho các hàng chứa 1:

   foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu
0     1.0         0             0        2         NA
1     2.1         0             1        4          0
2     NaN         0           NaN        1          0
5     6.8         1             0        5          0

Việc chọn hàng được thực hiện bởi

(df == 1).any(axis=1)

như trong câu trả lời của @ ajcr cung cấp cho bạn:

0     True
1     True
2     True
3    False
4    False
5     True
dtype: bool

nghĩa là hàng đó 34không chứa a 1và sẽ không được chọn.

Việc lựa chọn các cột được thực hiện bằng cách sử dụng lập chỉ mục Boolean như sau:

df.columns.map(lambda x: x.startswith('foo'))

Trong ví dụ trên, điều này trả về

array([False,  True,  True,  True,  True,  True, False], dtype=bool)

Vì vậy, nếu một cột không bắt đầu bằng foo, Falsesẽ được trả về và do đó cột đó không được chọn.

Nếu bạn chỉ muốn trả về tất cả các hàng có chứa a 1- như kết quả mong muốn của bạn cho thấy - bạn chỉ cần làm

df.loc[(df == 1).any(axis=1)]

cái nào trả về

   bar.baz  foo.aa  foo.bars  foo.fighters  foo.fox foo.manchu nas.foo
0      5.0     1.0         0             0        2         NA      NA
1      5.0     2.1         0             1        4          0       0
2      6.0     NaN         0           NaN        1          0       1
5      6.8     6.8         1             0        5          0       0

0

Bạn có thể thử regex tại đây để lọc ra các cột bắt đầu bằng "foo"

df.filter(regex='^foo*')

Nếu bạn cần có chuỗi foo trong cột của mình thì

df.filter(regex='foo*')

sẽ là thích hợp.

Đối với bước tiếp theo, bạn có thể sử dụng

df[df.filter(regex='^foo*').values==1]

để lọc ra các hàng có một trong các giá trị của cột 'foo *' là 1.


0

Trong trường hợp của tôi, tôi cần một danh sách các tiền tố

colsToScale=["production", "test", "development"]
dc[dc.columns[dc.columns.str.startswith(tuple(colsToScale))]]
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.