Giá trị thật của một Series là mơ hồ. Sử dụng a.empty, a.bool (), a.item (), a.any () hoặc a.all ()


368

Có vấn đề lọc khung dữ liệu kết quả của tôi với một orđiều kiện. Tôi muốn kết quả của tôi dftrích xuất tất cả các cộtvar giá trị cao hơn 0,25 và dưới -0,25.

Logic dưới đây mang lại cho tôi một giá trị chân lý mơ hồ tuy nhiên nó hoạt động khi tôi tách bộ lọc này thành hai thao tác riêng biệt. Có chuyện gì đang xảy ra ở đây? không chắc chắn nơi để sử dụng đề xuấta.empty(), a.bool(), a.item(),a.any() or a.all() .

 result = result[(result['var']>0.25) or (result['var']<-0.25)]

46
sử dụng |thay vìor
MaxU

1
Đây là một cách giải quyết:abs(result['var'])>0.25
ColinMac

Câu trả lời:


566

Các câu lệnh orandpython yêu cầu giá truthtrị. Đối với pandasnhững điều này được coi là mơ hồ, do đó bạn nên sử dụng các hoạt động "bitwise" |(hoặc) hoặc &(và):

result = result[(result['var']>0.25) | (result['var']<-0.25)]

Chúng bị quá tải cho các loại dữ liệu này để mang lại yếu tố khôn ngoan or(hoặc and).


Chỉ cần thêm một số giải thích cho tuyên bố này:

Trường hợp ngoại lệ được ném khi bạn muốn để có được boolmột pandas.Series:

>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Những gì bạn đạt được một nơi mà các nhà điều hành ngầm chuyển đổi các toán hạng để bool(bạn sử dụng ornhưng nó cũng xảy ra cho and, ifwhile):

>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Bên cạnh những 4 báo cáo có một số chức năng python mà ẩn một số boolcuộc gọi (như any, all, filter, ...) đây là những thường không có vấn đề với pandas.Seriesnhưng cho đầy đủ tôi muốn đề cập đến những.


Trong trường hợp của bạn, ngoại lệ không thực sự hữu ích, vì nó không đề cập đến các lựa chọn thay thế phù hợp . Cho andorbạn có thể sử dụng (nếu bạn muốn so sánh phần tử khôn ngoan):

  • numpy.logical_or:

    >>> import numpy as np
    >>> np.logical_or(x, y)

    hoặc đơn giản là |toán tử:

    >>> x | y
  • numpy.logical_and:

    >>> np.logical_and(x, y)

    hoặc đơn giản là &toán tử:

    >>> x & y

Nếu bạn đang sử dụng các toán tử thì hãy chắc chắn rằng bạn đặt dấu ngoặc đơn chính xác vì ưu tiên toán tử .

một số chức năng NumPy logicnên làm việc trên pandas.Series.


Các lựa chọn thay thế được đề cập trong Ngoại lệ sẽ phù hợp hơn nếu bạn gặp phải nó khi thực hiện ifhoặc while. Tôi sẽ giải thích ngắn gọn về từng điều sau:

  • Nếu bạn muốn kiểm tra xem Series của bạn có trống không :

    >>> x = pd.Series([])
    >>> x.empty
    True
    >>> x = pd.Series([1])
    >>> x.empty
    False

    Python thường diễn giải lenthứ g container (như list, tuple, ...) như là chân lý có giá trị nếu nó không có sự giải thích rõ ràng boolean. Vì vậy, nếu bạn muốn kiểm tra giống như con trăn, bạn có thể làm: if x.sizehoặc if not x.emptythay vì if x.

  • Nếu bạn Serieschứa một và chỉ một giá trị boolean:

    >>> x = pd.Series([100])
    >>> (x > 50).bool()
    True
    >>> (x < 50).bool()
    False
  • Nếu bạn muốn kiểm tra mục đầu tiên và duy nhất của Sê-ri của mình (thích .bool()nhưng hoạt động ngay cả đối với nội dung không phải là boolean):

    >>> x = pd.Series([100])
    >>> x.item()
    100
  • Nếu bạn muốn kiểm tra xem tất cả hoặc bất kỳ mục nào không phải là không, không trống hoặc không-Sai:

    >>> x = pd.Series([0, 1, 2])
    >>> x.all()   # because one element is zero
    False
    >>> x.any()   # because one (or more) elements are non-zero
    True

Tại sao các nhà khai thác trăn này không bị quá tải để xử lý loạt gấu trúc?
Mudit Jain

@MuditJain Không có cách nào để trực tiếp tình trạng quá tải and, ornotbằng Python. Các toán tử này sử dụng trực tiếp những gì booltrên toán hạng trả về. Và theo một cách nào đó, Pandas / NumPy đã quá tải mà đã tăng lên ValueErrorvì họ coi giá trị thật của một cấu trúc dữ liệu mơ hồ như vậy.
MSeifert

giải pháp là ổn, nhưng lời giải thích không tốt lắm
blacksheep

2
@blacksheep Bạn có gợi ý nào về những gì tôi có thể giải thích rõ hơn không?
MSeifert

Đó là một lời giải thích tuyệt vời. Nó thực sự giúp tôi hiểu bitwise vs logic theo cách mà các ví dụ trừu tượng hơn đã không làm được.
đáNaves

41

Đối với logic boolean, sử dụng &|.

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))

>>> df
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

Để xem những gì đang xảy ra, bạn nhận được một cột booleans cho mỗi so sánh, ví dụ:

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool

Khi bạn có nhiều tiêu chí, bạn sẽ nhận được nhiều cột được trả về. Đây là lý do tại sao logic tham gia là mơ hồ. Sử dụng andhoặc orxử lý từng cột riêng biệt, vì vậy trước tiên bạn cần giảm cột đó xuống một giá trị boolean duy nhất. Ví dụ: để xem liệu bất kỳ giá trị hoặc tất cả các giá trị trong mỗi cột là True.

# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True

# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False

Một cách phức tạp để đạt được điều tương tự là nén tất cả các cột này lại với nhau và thực hiện logic thích hợp.

>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

Để biết thêm chi tiết, hãy tham khảo Lập chỉ mục Boolean trong các tài liệu.


20

Vâng gấu trúc sử dụng bitwise '&' '|' và mỗi điều kiện nên được bọc trong một '()'

Ví dụ các công trình sau

data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]

Nhưng cùng một truy vấn không có dấu ngoặc thích hợp thì không

data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]

8

Hoặc, thay vào đó, bạn có thể sử dụng mô-đun Toán tử. Thông tin chi tiết hơn có ở đây Tài liệu Python

import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C > 0.25, df.C < -0.25)]

          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.4438

1

Câu trả lời tuyệt vời này giải thích rất tốt những gì đang xảy ra và cung cấp một giải pháp. Tôi muốn thêm một giải pháp khác có thể phù hợp trong các trường hợp tương tự: sử dụng queryphương pháp:

result = result.query("(var > 0.25) or (var < -0.25)")

Xem thêm http://pandas.pydata.org/pandas-docs/urdy/indexing.html#indexing-query .

(Một số thử nghiệm với khung dữ liệu tôi hiện đang làm việc với đề xuất rằng phương pháp này chậm hơn một chút so với sử dụng các toán tử bitwise trên loạt booleans: 2 ms so với 870 mật khẩu)

Một lời cảnh báo : Ít nhất một tình huống trong đó không đơn giản là khi tên cột xảy ra là biểu thức python. Tôi đã có các cột được đặt tên WT_38hph_IP_2, WT_38hph_input_2log2(WT_38hph_IP_2/WT_38hph_input_2) và muốn thực hiện các truy vấn sau đây:"(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

Tôi đã thu được các tầng ngoại lệ sau:

  • KeyError: 'log2'
  • UndefinedVariableError: name 'log2' is not defined
  • ValueError: "log2" is not a supported function

Tôi đoán điều này đã xảy ra bởi vì trình phân tích cú pháp truy vấn đã cố gắng tạo một cái gì đó từ hai cột đầu tiên thay vì xác định biểu thức với tên của cột thứ ba.

Một cách giải quyết có thể được đề xuất ở đây .


1

Tôi đã gặp lỗi tương tự và bị đình trệ với khung dữ liệu pyspark trong vài ngày, tôi đã có thể giải quyết thành công bằng cách điền giá trị na bằng 0 vì tôi đang so sánh giá trị số nguyên từ 2 trường.

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.