Repository: pandas-dev/pandas

Issue:
ValueError on df.columns.isin(pd.Series())
#### Code Sample, a copy-pastable example if possible

```python
    df = pd.DataFrame(columns=list('ab'))
    s1 = pd.Series(['a'])
    s2 = pd.Series()
    df.columns.isin(s1)
    df.columns.isin(s2)

```
#### Problem description

The second call to `df.columns.isin(s2)` fails with 

    D:\Anaconda\envs\py3k\lib\site-packages\pandas\core\algorithms.py in <lambda>(x, y)
        402     # work-around for numpy < 1.8 and comparisions on py3
        403     # faster for larger cases to use np.in1d
    --> 404     f = lambda x, y: htable.ismember_object(x, values)
        405     if (_np_version_under1p8 and compat.PY3) or len(comps) > 1000000:
        406         f = lambda x, y: np.in1d(x, y)

    pandas\_libs\hashtable_func_helper.pxi in pandas._libs.hashtable.ismember_object (pandas\_libs\hashtable.c:30162)()

    ValueError: Buffer dtype mismatch, expected 'Python object' but got 'double'

#### Expected Output

    array([ False, False], dtype=bool)

#### Output of ``pd.show_versions()``

    INSTALLED VERSIONS
    ------------------
    commit: None
    python: 3.5.3.final.0
    python-bits: 64
    OS: Windows
    OS-release: 10
    machine: AMD64

    pandas: 0.20.3
    numpy: 1.13.1


Might be linked to [#16394](https://github.com/pandas-dev/pandas/issues/16394)



Discussion:
Reproduced on `master`.  That's a bug alright.  PR is welcome!
@jreback : Tagging this for `0.21` because IMO we should be able to address this bug for the release.  If no one picks it up, I can patch it before then.
i almost always tag with next release 

otherwise u end up moving them later back if they r not done 

just so many reports it's hard to judge what to tag unless there is an actual PR
> otherwise u end up moving them later back if they r not done

That's true.  I do have this one on my radar though, so when the time comes to release and this still hasn't been resolved, feel free to call me out on it :smile: 

Resolving patch:
diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py
--- a/pandas/core/algorithms.py
+++ b/pandas/core/algorithms.py
@@ -65,6 +65,8 @@ def _ensure_data(values, dtype=None):
 
     # we check some simple dtypes first
     try:
+        if is_object_dtype(dtype):
+            return _ensure_object(np.asarray(values)), 'object', 'object'
         if is_bool_dtype(values) or is_bool_dtype(dtype):
             # we are actually coercing to uint64
             # until our algos suppport uint8 directly (see TODO)


Test patch:
diff --git a/pandas/tests/frame/test_analytics.py b/pandas/tests/frame/test_analytics.py
--- a/pandas/tests/frame/test_analytics.py
+++ b/pandas/tests/frame/test_analytics.py
@@ -1151,10 +1151,13 @@ def test_isin(self):
         expected = DataFrame([df.loc[s].isin(other) for s in df.index])
         tm.assert_frame_equal(result, expected)
 
-    def test_isin_empty(self):
+    @pytest.mark.parametrize("empty", [[], Series(), np.array([])])
+    def test_isin_empty(self, empty):
+        # see gh-16991
         df = DataFrame({'A': ['a', 'b', 'c'], 'B': ['a', 'e', 'f']})
-        result = df.isin([])
-        expected = pd.DataFrame(False, df.index, df.columns)
+        expected = DataFrame(False, df.index, df.columns)
+
+        result = df.isin(empty)
         tm.assert_frame_equal(result, expected)
 
     def test_isin_dict(self):
diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py
--- a/pandas/tests/indexes/test_base.py
+++ b/pandas/tests/indexes/test_base.py
@@ -1407,6 +1407,15 @@ def check_idx(idx):
         # Float64Index overrides isin, so must be checked separately
         check_idx(Float64Index([1.0, 2.0, 3.0, 4.0]))
 
+    @pytest.mark.parametrize("empty", [[], Series(), np.array([])])
+    def test_isin_empty(self, empty):
+        # see gh-16991
+        idx = Index(["a", "b"])
+        expected = np.array([False, False])
+
+        result = idx.isin(empty)
+        tm.assert_numpy_array_equal(expected, result)
+
     def test_boolean_cmp(self):
         values = [1, 2, 3, 4]
 
diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py
--- a/pandas/tests/series/test_analytics.py
+++ b/pandas/tests/series/test_analytics.py
@@ -1135,6 +1135,15 @@ def test_isin_with_i8(self):
         result = s.isin(s[0:2])
         assert_series_equal(result, expected)
 
+    @pytest.mark.parametrize("empty", [[], Series(), np.array([])])
+    def test_isin_empty(self, empty):
+        # see gh-16991
+        s = Series(["a", "b"])
+        expected = Series([False, False])
+
+        result = s.isin(empty)
+        tm.assert_series_equal(expected, result)
+
     def test_timedelta64_analytics(self):
         from pandas import date_range
 
diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py
--- a/pandas/tests/test_algos.py
+++ b/pandas/tests/test_algos.py
@@ -597,6 +597,15 @@ def test_categorical_from_codes(self):
         result = algos.isin(Sd, St)
         tm.assert_numpy_array_equal(expected, result)
 
+    @pytest.mark.parametrize("empty", [[], pd.Series(), np.array([])])
+    def test_empty(self, empty):
+        # see gh-16991
+        vals = pd.Index(["a", "b"])
+        expected = np.array([False, False])
+
+        result = algos.isin(vals, empty)
+        tm.assert_numpy_array_equal(expected, result)
+
 
 class TestValueCounts(object):