Gấu trúc Cách lọc một chuỗi


94

Tôi có một Chuỗi như thế này sau khi thực hiện groupby ('name') và sử dụng hàm mean () trên cột khác

name
383      3.000000
663      1.000000
726      1.000000
737      9.000000
833      8.166667

Bất cứ ai có thể vui lòng chỉ cho tôi cách lọc ra các hàng có giá trị trung bình 1.000000 được không? Cảm ơn bạn và tôi đánh giá rất cao sự giúp đỡ của bạn.


Chà, bạn sẽ lọc một chuỗi theo một điều kiện nhất định như thế nào?

Câu trả lời:


127
In [5]:

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s = s[s != 1]
s
Out[0]:
383    3.000000
737    9.000000
833    8.166667
dtype: float64

10
Tôi thích các câu trả lời dưới đây hơn vì chúng có thể được xâu chuỗi (tức là không cần xác định svà sau đó sử dụng nó hai lần trong biểu thức). Tuy nhiên, chỉ hoạt động từ gấu trúc 0,18.
IanS

Cũng xem so sánh thời gian trong câu trả lời của piRSquared .
IanS

63

Từ phiên bản gấu trúc 0.18+, việc lọc một loạt cũng có thể được thực hiện như bên dưới

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

pd.Series(test).where(lambda x : x!=1).dropna()

Thanh toán: http://pandas.pydata.org/pandas-docs/version/0.18.1/whatsnew.html#method-chaininng-improvements


3
Đẹp hơn rất nhiều với chuỗi phương pháp (và làm tôi nhớ đến Spark.)
Dylan Hogg

Đúng nhưng Spark làm điều gì đó trực quan hơn trong trường hợp này: nó chỉ đơn giản là loại bỏ các hàng không khớp với vị ngữ, có nghĩa là không sử dụng phần ".dropna ()" mà dường như rõ ràng là thừa đối với tôi cho đến khi tôi đọc tài liệu.
Bị

44

Như DACW đã chỉ ra , có những cải tiến về chuỗi phương pháp trong gấu trúc 0.18.1 thực hiện những gì bạn đang tìm kiếm rất độc đáo.

Thay vì sử dụng .where, bạn có thể chuyển hàm của mình cho trình .loclập chỉ mục hoặc trình chỉ mục Series []và tránh lệnh gọi đến .dropna:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.loc[lambda x : x!=1]

test[lambda x: x!=1]

Hành vi tương tự được hỗ trợ trên các lớp DataFrame và NDFrame.


2
Đây là câu trả lời yêu thích của tôi, và nó cũng có vẻ là nhanh nhất mà không cần phải đi xuống (xem so sánh thời gian).
IanS

21

Một cách nhanh chóng để làm điều này là tái tạo lại bằng cách sử dụng numpyđể cắt các mảng bên dưới. Xem thời gian bên dưới.

mask = s.values != 1
pd.Series(s.values[mask], s.index[mask])

0
383    3.000000
737    9.000000
833    8.166667
dtype: float64

thời điểm ngây thơ

nhập mô tả hình ảnh ở đây


, Tôi thích phương pháp của bạn, tôi muốn biết điều gì sẽ xảy ra nếu tôi đắp nhiều mặt nạ. Thx
Menglong Li

1
@MenglongLi tùy, bạn nên đặt một câu hỏi. Rất có thể, bạn sẽ kết hợp chúng với &. mặt nạ = mask1 & mask2
piRSquared

6

Một cách khác là trước tiên chuyển đổi sang DataFrame và sử dụng phương pháp truy vấn (giả sử bạn đã cài đặt sốxpr):

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s.to_frame(name='x').query("x != 1")

Tôi không nghĩ rằng đó là một ý tưởng tốt để vượt qua một điều kiện như là một chuỗi
SzymonPajzert

1
Điều này thêm tất cả chi phí của khung dữ liệu và sẽ rất chậm.
fantabolous

5

Nếu bạn thích một hoạt động theo chuỗi, bạn cũng có thể sử dụng compresshàm:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.compress(lambda x: x != 1)

# 383    3.000000
# 737    9.000000
# 833    8.166667
# dtype: float64

1

Trong trường hợp của tôi, tôi có một Chuỗi gấu trúc trong đó các giá trị là các bộ ký tự :

Out[67]
0    (H, H, H, H)
1    (H, H, H, T)
2    (H, H, T, H)
3    (H, H, T, T)
4    (H, T, H, H)

Do đó, tôi có thể sử dụng lập chỉ mục để lọc chuỗi, nhưng để tạo chỉ mục tôi cần apply. Điều kiện của tôi là "tìm tất cả các bộ giá trị có đúng một 'H'".

series_of_tuples[series_of_tuples.apply(lambda x: x.count('H')==1)]

Tôi thừa nhận nó không phải"chainable" , (nghĩa là tôi lặp lại series_of_tupleshai lần; bạn phải lưu trữ bất kỳ chuỗi tạm thời nào vào một biến để bạn có thể gọi apply (...) trên đó).

Cũng có thể có các phương thức khác (ngoài ra .apply(...)) có thể hoạt động theo từng phần tử để tạo ra chỉ số Boolean.

Nhiều câu trả lời khác (bao gồm cả câu trả lời được chấp nhận) sử dụng các chức năng có thể phân tích được như:

  • .compress()
  • .where()
  • .loc[]
  • []

Chúng chấp nhận các giá trị có thể gọi (lambdas) được áp dụng cho Chuỗi , không áp dụng cho các giá trị riêng lẻ trong chuỗi đó!

Do đó, loạt bộ giá trị của tôi hoạt động kỳ lạ khi tôi cố gắng sử dụng điều kiện / callable / lambda ở trên của mình, với bất kỳ hàm nào có thể điều khiển được, như .loc[]:

series_of_tuples.loc[lambda x: x.count('H')==1]

Tạo ra lỗi:

KeyError: 'Cấp H phải giống với tên (Không có)'

Tôi đã rất bối rối, nhưng có vẻ như nó đang sử dụng hàm Series.countseries_of_tuples.count(...) , không phải là những gì tôi muốn.

Tôi thừa nhận rằng một cấu trúc dữ liệu thay thế có thể tốt hơn:

  • Một kiểu dữ liệu Danh mục?
  • Khung dữ liệu (mỗi phần tử của tuple trở thành một cột)
  • Một loạt các chuỗi (chỉ cần nối các bộ giá trị với nhau):

Điều này tạo ra một chuỗi các chuỗi (tức là bằng cách nối bộ tuple; nối các ký tự trong bộ vào một chuỗi duy nhất)

series_of_tuples.apply(''.join)

Vì vậy, tôi sau đó có thể sử dụng thể kết nốiSeries.str.count

series_of_tuples.apply(''.join).str.count('H')==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.