Repository: pandas-dev/pandas

Issue:
BLD: bool block failures on py 3.3 from GH6339
see #6339



Discussion:
This also doesn't work on py 2. Not sure why it isn't failing.

It's the same error though, which means I don't have to use py33 to debug, yay!

its related to the duplicates.....I think, just blinding looking that you need to set ref_locs if a dup indexed block is created

ironically this is code that i wrote or moved around for regex replace

The issue arises bc the following code doesn't perform element wise comparison

``` python
x = randn(2)
y = 'x'
z = x == y
```

whereas if `y` is numeric it does perform element-wise comparison

where does that happen? 

`replace_list` nested function called `comp`, i have a fix

ahh...i see....something which I 'fixed' for anothe issue

yep ... fix coming in 5 minutes-ish ... cutting it close ... but anything for pandas :)

And it works in other cases because you have an `object` array, which _will_ perform element wise comparison


Resolving patch:
diff --git a/pandas/core/common.py b/pandas/core/common.py
--- a/pandas/core/common.py
+++ b/pandas/core/common.py
@@ -359,20 +359,18 @@ def mask_missing(arr, values_to_mask):
         if mask is None:
             mask = arr == x
 
-            # if x is a string and mask is not, then we get a scalar
-            # return value, which is not good
-            if not isinstance(mask, np.ndarray):
-                m = mask
-                mask = np.empty(arr.shape, dtype=np.bool)
-                mask.fill(m)
+            # if x is a string and arr is not, then we get False and we must
+            # expand the mask to size arr.shape
+            if np.isscalar(mask):
+                mask = np.zeros(arr.shape, dtype=bool)
         else:
-            mask = mask | (arr == x)
+            mask |= arr == x
 
     if na_mask.any():
         if mask is None:
             mask = isnull(arr)
         else:
-            mask = mask | isnull(arr)
+            mask |= isnull(arr)
 
     return mask
 
diff --git a/pandas/core/internals.py b/pandas/core/internals.py
--- a/pandas/core/internals.py
+++ b/pandas/core/internals.py
@@ -1,5 +1,6 @@
 import itertools
 import re
+import operator
 from datetime import datetime, timedelta
 import copy
 from collections import defaultdict
@@ -2453,7 +2454,8 @@ def replace_list(self, src_list, dest_list, inplace=False, regex=False):
         def comp(s):
             if isnull(s):
                 return isnull(values)
-            return values == getattr(s, 'asm8', s)
+            return _possibly_compare(values, getattr(s, 'asm8', s),
+                                     operator.eq)
         masks = [comp(s) for i, s in enumerate(src_list)]
 
         result_blocks = []
@@ -4153,3 +4155,20 @@ def _possibly_convert_to_indexer(loc):
     elif isinstance(loc, slice):
         loc = lrange(loc.start, loc.stop)
     return loc
+
+
+def _possibly_compare(a, b, op):
+    res = op(a, b)
+    is_a_array = isinstance(a, np.ndarray)
+    is_b_array = isinstance(b, np.ndarray)
+    if np.isscalar(res) and (is_a_array or is_b_array):
+        type_names = [type(a).__name__, type(b).__name__]
+
+        if is_a_array:
+            type_names[0] = 'ndarray(dtype=%s)' % a.dtype
+
+        if is_b_array:
+            type_names[1] = 'ndarray(dtype=%s)' % b.dtype
+
+        raise TypeError("Cannot compare types %r and %r" % tuple(type_names))
+    return res


Test patch:
diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py
--- a/pandas/tests/test_frame.py
+++ b/pandas/tests/test_frame.py
@@ -8005,9 +8005,8 @@ def test_replace_bool_with_bool(self):
 
     def test_replace_with_dict_with_bool_keys(self):
         df = DataFrame({0: [True, False], 1: [False, True]})
-        result = df.replace({'asdf': 'asdb', True: 'yes'})
-        expected = DataFrame({0: ['yes', False], 1: [False, 'yes']})
-        tm.assert_frame_equal(expected, result)
+        with tm.assertRaisesRegexp(TypeError, 'Cannot compare types .+'):
+            df.replace({'asdf': 'asdb', True: 'yes'})
 
     def test_combine_multiple_frames_dtypes(self):
         from pandas import concat
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -5264,7 +5264,11 @@ def test_replace(self):
 
         # malformed
         self.assertRaises(ValueError, ser.replace, [1, 2, 3], [np.nan, 0])
-        self.assertRaises(TypeError, ser.replace, range(1, 3), [np.nan, 0])
+
+        # make sure that we aren't just masking a TypeError because bools don't
+        # implement indexing
+        with tm.assertRaisesRegexp(TypeError, 'Cannot compare types .+'):
+            ser.replace([1, 2], [np.nan, 0])
 
         ser = Series([0, 1, 2, 3, 4])
         result = ser.replace([0, 1, 2, 3, 4], [4, 3, 2, 1, 0])
@@ -5369,9 +5373,8 @@ def test_replace_bool_with_bool(self):
 
     def test_replace_with_dict_with_bool_keys(self):
         s = Series([True, False, True])
-        result = s.replace({'asdf': 'asdb', True: 'yes'})
-        expected = Series(['yes', False, 'yes'])
-        tm.assert_series_equal(expected, result)
+        with tm.assertRaisesRegexp(TypeError, 'Cannot compare types .+'):
+            s.replace({'asdf': 'asdb', True: 'yes'})
 
     def test_asfreq(self):
         ts = Series([0., 1., 2.], index=[datetime(2009, 10, 30),