Làm cách nào tôi có thể có được logic logic khôn ngoan của một chuỗi gấu trúc?


229

Tôi có một con gấu trúc Series đối tượng chứa các giá trị boolean. Làm cách nào tôi có thể nhận được một chuỗi chứa logic NOTcủa từng giá trị?

Ví dụ, hãy xem xét một loạt có chứa:

True
True
True
False

Loạt bài tôi muốn nhận sẽ chứa:

False
False
False
True

Điều này có vẻ như khá đơn giản, nhưng rõ ràng là tôi đã đặt nhầm mojo của mình = (


1
Điều quan trọng là dữ liệu không chứa các objectloại để các câu trả lời bên dưới hoạt động, vì vậy hãy sử dụng:~ df.astype('bool')
LearnOPhile

Tôi đã viết về tất cả các toán tử logic trong bài viết này . Bài viết cũng bao gồm các lựa chọn thay thế.
cs95

Câu trả lời:


260

Để đảo ngược một chuỗi boolean, sử dụng~s :

In [7]: s = pd.Series([True, True, False, True])

In [8]: ~s
Out[8]: 
0    False
1    False
2     True
3    False
dtype: bool

Sử dụng Python2.7, NumPy 1.8.0, Pandas 0.13.1:

In [119]: s = pd.Series([True, True, False, True]*10000)

In [10]:  %timeit np.invert(s)
10000 loops, best of 3: 91.8 µs per loop

In [11]: %timeit ~s
10000 loops, best of 3: 73.5 µs per loop

In [12]: %timeit (-s)
10000 loops, best of 3: 73.5 µs per loop

Kể từ Pandas 0.13.0, Series không còn là lớp con của numpy.ndarray; bây giờ chúng là các lớp con của pd.NDFrame. Điều này có thể có liên quan đến lý do tại sao np.invert(s)không còn nhanh như ~shoặc -s.

Hãy cẩn thận: timeitkết quả có thể thay đổi tùy thuộc vào nhiều yếu tố bao gồm các phiên bản phần cứng, trình biên dịch, hệ điều hành, Python, NumPy và Pandas.


Ghi nhận hợp lệ. Khác với việc chậm hơn nhiều, sự khác biệt giữa dấu ngã và -?
blz

Wierd, tôi thực sự đã thử nghiệm tildenhư nó đã được đề cập trong tài liệu, nhưng nó không thực hiện giống như np.invert: S
root

@blz: Ít nhất trên máy tính Ubuntu của tôi, chạy NumPy 1.6.2, hiệu suất của np.invert(s), ~s-stất cả đều giống nhau.
unutbu

@root: Tôi không chắc tại sao có sự khác biệt lớn như vậy trong kết quả thời gian của chúng tôi, nhưng nó chắc chắn có thể xảy ra. Bạn đang sử dụng hệ điều hành và phiên bản NumPy nào?
unutbu

Cũng trên Ubuntu, nhưng sử dụng NumPy 1.7.0 ... ( np.bitwise_not(s)thực hiện giống như np.inverse).
gốc

32

Câu trả lời của @ unutbu là tại chỗ, chỉ muốn thêm một cảnh báo rằng mặt nạ của bạn cần phải là dtype bool, không phải là 'đối tượng'. Tức là mặt nạ của bạn chưa bao giờ có nan. Xem tại đây - ngay cả khi mặt nạ của bạn hiện không có nan, nó sẽ vẫn là loại 'đối tượng'.

Nghịch đảo của một chuỗi 'đối tượng' sẽ không gây ra lỗi, thay vào đó bạn sẽ nhận được một mặt nạ rác của các int không hoạt động như bạn mong đợi.

In[1]: df = pd.DataFrame({'A':[True, False, np.nan], 'B':[True, False, True]})
In[2]: df.dropna(inplace=True)
In[3]: df['A']
Out[3]:
0    True
1   False
Name: A, dtype object
In[4]: ~df['A']
Out[4]:
0   -2
0   -1
Name: A, dtype object

Sau khi nói chuyện với các đồng nghiệp về điều này, tôi có một lời giải thích: Có vẻ như gấu trúc đang quay trở lại toán tử bitwise:

In [1]: ~True
Out[1]: -2

Như @geher nói, bạn có thể chuyển đổi nó thành bool với astype trước khi bạn nghịch đảo với ~

~df['A'].astype(bool)
0    False
1     True
Name: A, dtype: bool
(~df['A']).astype(bool)
0    True
1    True
Name: A, dtype: bool

trong ví dụ của bạn, sản lượng ints mặt nạ có thể được chuyển đổi sang loạt bool bạn muốn với .astype(bool)ví dụ~df['A'].astype(bool)
geher

Điều này đang hoạt động vì astype(bool)đang diễn ra trước ~ ~df['A'].astype(bool)vs(~df['A']).astype(bool)
JSharm

16

Tôi chỉ cho nó một shot:

In [9]: s = Series([True, True, True, False])

In [10]: s
Out[10]: 
0     True
1     True
2     True
3    False

In [11]: -s
Out[11]: 
0    False
1    False
2    False
3     True

Tôi thực sự đã thử mọi nhà điều hành khác hơn -! Tôi sẽ ghi nhớ điều này cho lần tới.
blz

6

Bạn cũng có thể sử dụng numpy.invert:

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: s = pd.Series([True, True, False, True])

In [4]: np.invert(s)
Out[4]: 
0    False
1    False
2     True
3    False

EDIT: Sự khác biệt về hiệu suất xuất hiện trên Ubuntu 12.04, Python 2.7, NumPy 1.7.0 - dường như không tồn tại khi sử dụng NumPy 1.6.2:

In [5]: %timeit (-s)
10000 loops, best of 3: 26.8 us per loop

In [6]: %timeit np.invert(s)
100000 loops, best of 3: 7.85 us per loop

In [7]: %timeit ~s
10000 loops, best of 3: 27.3 us per loop

nó có thể không đúng trên một nền tảng khác. Win 7, python 3.6.3 numpy 1.13.3, pandas 0.20.3, (-s) sẽ là nhanh nhất, (~ s) là thứ hai và np.invert (s) là người chậm nhất
gaozhidf

0

NumPy chậm hơn vì nó chuyển đầu vào thành các giá trị boolean (vì vậy Không và 0 trở thành Sai và mọi thứ khác trở thành Đúng).

import pandas as pd
import numpy as np
s = pd.Series([True, None, False, True])
np.logical_not(s)

mang đến cho bạn

0    False
1     True
2     True
3    False
dtype: object

trong khi đó ~ s sẽ sụp đổ. Trong hầu hết các trường hợp, dấu ngã sẽ là sự lựa chọn an toàn hơn NumPy.

Gấu trúc 0,25, NumPy 1,17

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.