Skip to content

Commit 5229ac6

Browse files
committed
BUG: consistency between logical ops & type casts
1 parent f505097 commit 5229ac6

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

doc/source/v0.15.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -650,4 +650,4 @@ Bug Fixes
650650
- Bug in accessing groups from a ``GroupBy`` when the original grouper
651651
was a tuple (:issue:`8121`).
652652

653-
653+
- Bug in logical operations of series and their consistency with type casts (:issue:`6528`)

pandas/core/ops.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -636,10 +636,12 @@ def wrapper(self, other):
636636
if isinstance(other, pd.Series):
637637
name = _maybe_match_name(self, other)
638638

639-
other = other.reindex_like(self).fillna(False).astype(bool)
640-
return self._constructor(na_op(self.values, other.values),
639+
left = self.astype(bool).values
640+
right = other.astype(bool).reindex_like(self)
641+
right = right.fillna(False).values
642+
return self._constructor(na_op(left, right),
641643
index=self.index,
642-
name=name).fillna(False).astype(bool)
644+
name=name)
643645
elif isinstance(other, pd.DataFrame):
644646
return NotImplemented
645647
else:

pandas/tests/test_frame.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4992,7 +4992,7 @@ def test_logical_with_nas(self):
49924992
# GH4947
49934993
# bool comparisons should return bool
49944994
result = d['a'] | d['b']
4995-
expected = Series([False, True])
4995+
expected = Series(np.logical_or(d['a'], d['b']), dtype='bool')
49964996
assert_series_equal(result, expected)
49974997

49984998
# GH4604, automatic casting here

pandas/tests/test_series.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -2368,6 +2368,31 @@ def check(series, other, check_reverse=False):
23682368
check(self.ts, 5, check_reverse=True)
23692369
check(tm.makeFloatSeries(), tm.makeFloatSeries(), check_reverse=True)
23702370

2371+
def test_bool_op(self): # GH6528 & GH8151
2372+
u = pd.Series([nan, nan, nan, False, False, True, True])
2373+
v = pd.Series([nan, False, True, False, True, False, True])
2374+
2375+
for a, b in [[u, v], [v, u]]:
2376+
# against numpy logical casted to bool
2377+
assert_series_equal(a | b, Series(np.logical_or(a, b), dtype='bool'))
2378+
assert_series_equal(a & b, Series(np.logical_and(a, b), dtype='bool'))
2379+
assert_series_equal(a ^ b, # np.logical_xor throws with floats!
2380+
Series(np.logical_xor(a.values.astype(bool),
2381+
b.values.astype(bool))))
2382+
2383+
assert_series_equal(~ a.astype(bool),
2384+
Series(np.logical_not(a), dtype='bool'))
2385+
2386+
# type cast semantics
2387+
assert_series_equal(a | b, a.astype(bool) | b.astype(bool))
2388+
assert_series_equal(a & b, a.astype(bool) & b.astype(bool))
2389+
assert_series_equal(a ^ b, a.astype(bool) ^ b.astype(bool))
2390+
2391+
# symmetry
2392+
assert_series_equal(a & b, b & a)
2393+
assert_series_equal(a | b, b | a)
2394+
assert_series_equal(a ^ b, b ^ a)
2395+
23712396
def test_neg(self):
23722397
assert_series_equal(-self.series, -1 * self.series)
23732398

@@ -3418,7 +3443,7 @@ def test_comparison_label_based(self):
34183443

34193444
# identity
34203445
# we would like s[s|e] == s to hold for any e, whether empty or not
3421-
for e in [Series([]),Series([1],['z']),Series(['z']),Series(np.nan,b.index),Series(np.nan,a.index)]:
3446+
for e in [Series([]),Series([1],['z']),Series(['z']),Series(False,b.index),Series(False,a.index)]:
34223447
result = a[a | e]
34233448
assert_series_equal(result,a[a])
34243449

@@ -6144,4 +6169,3 @@ def test_unique_data_ownership(self):
61446169
if __name__ == '__main__':
61456170
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
61466171
exit=False)
6147-

0 commit comments

Comments
 (0)