Repository: pandas-dev/pandas

Issue:
MultiIndex.get_leves_values() returns inconsistent Index if there are NaNs
#### Code Sample, a copy-pastable example if possible

```python
In [3]: pd.MultiIndex.from_arrays([['a', 'b', 'b'], [2, np.nan, 2]]).get_level_values(1)
Out[3]: Int64Index([2.0, nan, 2.0], dtype='float64')
```
#### Problem description

An ``Int64Index`` should never have ``dtype='float64'``.

Ironically, this is tested extensively in ``test_get_level_values_na`` inside ``pandas/tests/indexes/test_multi.py``, except that then the result is [explicitly casted](https://github.com/pandas-dev/pandas/blob/master/pandas/tests/indexes/test_multi.py#L963) (this came out from [this comment](https://github.com/pandas-dev/pandas/pull/17897#discussion_r145427829) by Joris).

I'm pretty sure the bug comes from [this line](https://github.com/pandas-dev/pandas/blob/master/pandas/core/indexes/multi.py#L909), but at the moment I'm not sure what should replace it.

#### Expected Output
```python
Float64Index([2.0, nan, 2.0], dtype='float64')
```
#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: 51c5f4d2a20179041114fac0262ef567d0b0373f
python: 3.5.3.final.0
python-bits: 64
OS: Linux
OS-release: 4.9.0-3-amd64
machine: x86_64
processor: 
byteorder: little
LC_ALL: None
LANG: it_IT.UTF-8
LOCALE: it_IT.UTF-8

pandas: 0.21.0rc1+26.g51c5f4d2a
pytest: 3.0.6
pip: 9.0.1
setuptools: None
Cython: 0.25.2
numpy: 1.12.1
scipy: 0.19.0
pyarrow: None
xarray: None
IPython: 5.1.0.dev
sphinx: 1.5.6
patsy: 0.4.1
dateutil: 2.6.0
pytz: 2017.2
blosc: None
bottleneck: 1.2.1
tables: 3.3.0
numexpr: 2.6.1
feather: 0.3.1
matplotlib: 2.0.0
openpyxl: None
xlrd: 1.0.0
xlwt: 1.1.2
xlsxwriter: 0.9.6
lxml: None
bs4: 4.5.3
html5lib: 0.999999999
sqlalchemy: 1.0.15
pymysql: None
psycopg2: None
jinja2: 2.9.6
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: 0.2.1


</details>



Discussion:

Resolving patch:
diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py
--- a/pandas/core/indexes/numeric.py
+++ b/pandas/core/indexes/numeric.py
@@ -62,6 +62,14 @@ def _maybe_cast_slice_bound(self, label, side, kind):
         # we will try to coerce to integers
         return self._maybe_cast_indexer(label)
 
+    @Appender(_index_shared_docs['_shallow_copy'])
+    def _shallow_copy(self, values=None, **kwargs):
+        if values is not None and not self._can_hold_na:
+            # Ensure we are not returning an Int64Index with float data:
+            return self._shallow_copy_with_infer(values=values, **kwargs)
+        return (super(NumericIndex, self)._shallow_copy(values=values,
+                                                        **kwargs))
+
     def _convert_for_op(self, value):
         """ Convert value to be insertable to ndarray """
 
@@ -395,9 +403,11 @@ def __contains__(self, other):
             try:
                 return len(other) <= 1 and ibase._try_get_item(other) in self
             except TypeError:
-                return False
-        except:
-            return False
+                pass
+        except TypeError:
+            pass
+
+        return False
 
     @Appender(_index_shared_docs['get_loc'])
     def get_loc(self, key, method=None, tolerance=None):


Test patch:
diff --git a/pandas/tests/indexes/test_multi.py b/pandas/tests/indexes/test_multi.py
--- a/pandas/tests/indexes/test_multi.py
+++ b/pandas/tests/indexes/test_multi.py
@@ -997,8 +997,8 @@ def test_get_level_values(self):
         exp = CategoricalIndex([1, 2, 3, 1, 2, 3])
         tm.assert_index_equal(index.get_level_values(1), exp)
 
-    @pytest.mark.xfail(reason='GH 17924 (returns Int64Index with float data)')
     def test_get_level_values_int_with_na(self):
+        # GH 17924
         arrays = [['a', 'b', 'b'], [1, np.nan, 2]]
         index = pd.MultiIndex.from_arrays(arrays)
         result = index.get_level_values(1)
@@ -1024,14 +1024,27 @@ def test_get_level_values_na(self):
 
         arrays = [['a', 'b', 'b'], pd.DatetimeIndex([0, 1, pd.NaT])]
         index = pd.MultiIndex.from_arrays(arrays)
-        values = index.get_level_values(1)
+        result = index.get_level_values(1)
         expected = pd.DatetimeIndex([0, 1, pd.NaT])
-        tm.assert_index_equal(values, expected)
+        tm.assert_index_equal(result, expected)
 
         arrays = [[], []]
         index = pd.MultiIndex.from_arrays(arrays)
-        values = index.get_level_values(0)
-        assert values.shape == (0, )
+        result = index.get_level_values(0)
+        expected = pd.Index([], dtype=object)
+        tm.assert_index_equal(result, expected)
+
+    def test_get_level_values_all_na(self):
+        # GH 17924 when level entirely consists of nan
+        arrays = [[np.nan, np.nan, np.nan], ['a', np.nan, 1]]
+        index = pd.MultiIndex.from_arrays(arrays)
+        result = index.get_level_values(0)
+        expected = pd.Index([np.nan, np.nan, np.nan], dtype=np.float64)
+        tm.assert_index_equal(result, expected)
+
+        result = index.get_level_values(1)
+        expected = pd.Index(['a', np.nan, 1], dtype=object)
+        tm.assert_index_equal(result, expected)
 
     def test_reorder_levels(self):
         # this blows up