Repository: pandas-dev/pandas

Issue:
iloc with empty list raises IndexError
When you slice a dataframe with an empty list you get an IndexError instead of an empty dataframe. Slicing with a non-empty list works fine.  Tested in pandas 0.13.1.  This is a regression from pandas 0.11.0.

``` python
df = pd.DataFrame(np.arange(25.0).reshape((5,5)), columns=list('abcde'))
```

Slice with non-empty list.

``` python
[5 rows x 5 columns]
df.iloc[[1,2,3]]
Out[34]: 
    a   b   c   d   e
1   5   6   7   8   9
2  10  11  12  13  14
3  15  16  17  18  19

[3 rows x 5 columns]
```

Slice with empty list.

``` python
df.iloc[[]]
Traceback (most recent call last):
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/ipython-1.1.0_1_ahl1-py2.7.egg/IPython/core/interactiveshell.py", line 2830, in run_code
    exec code_obj in self.user_global_ns, self.user_ns
  File "<ipython-input-35-8806137779f8>", line 1, in <module>
    df.iloc[[]]
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/indexing.py", line 1028, in __getitem__
    return self._getitem_axis(key, axis=0)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/indexing.py", line 1238, in _getitem_axis
    return self._get_loc(key, axis=axis)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/indexing.py", line 73, in _get_loc
    return self.obj._ixs(key, axis=axis)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/frame.py", line 1588, in _ixs
    result = self.reindex(i, takeable=True)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/frame.py", line 2162, in reindex
    **kwargs)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/generic.py", line 1565, in reindex
    takeable=takeable).__finalize__(self)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/frame.py", line 2117, in _reindex_axes
    fill_value, limit, takeable=takeable)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/frame.py", line 2126, in _reindex_index
    takeable=takeable)
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/index.py", line 1233, in reindex
    return self[target], target
  File "/users/is/dbew/pyenvs/timeseries/lib/python2.7/site-packages/pandas-0.13.1-py2.7-linux-x86_64.egg/pandas/core/index.py", line 624, in __getitem__
    result = arr_idx[key]
IndexError: arrays used as indices must be of integer (or boolean) type
```



Discussion:
Forgot to say, this works fine with .ix.

thanks...this is a bug


Resolving patch:
diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py
--- a/pandas/core/indexing.py
+++ b/pandas/core/indexing.py
@@ -1555,6 +1555,10 @@ def _maybe_convert_indices(indices, n):
     """
     if isinstance(indices, list):
         indices = np.array(indices)
+        if len(indices) == 0:
+            # If list is empty, np.array will return float and cause indexing
+            # errors.
+            return np.empty(0, dtype=np.int_)
 
     mask = indices < 0
     if mask.any():


Test patch:
diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py
--- a/pandas/tests/test_indexing.py
+++ b/pandas/tests/test_indexing.py
@@ -3175,6 +3175,26 @@ def test_set_ix_out_of_bounds_axis_1(self):
         df = pd.DataFrame(randn(5, 2), index=["row%s" % i for i in range(5)], columns=["col%s" % i for i in range(2)])
         self.assertRaises(ValueError, df.ix.__setitem__, (0 , 2), 100)
 
+    def test_iloc_empty_list_indexer_is_ok(self):
+        from pandas.util.testing import makeCustomDataframe as mkdf
+        df = mkdf(5, 2)
+        assert_frame_equal(df.iloc[:,[]], df.iloc[:, :0])  # vertical empty
+        assert_frame_equal(df.iloc[[],:], df.iloc[:0, :])  # horizontal empty
+
+    # FIXME: fix loc & xs
+    def test_loc_empty_list_indexer_is_ok(self):
+        raise nose.SkipTest('loc discards columns names')
+        from pandas.util.testing import makeCustomDataframe as mkdf
+        df = mkdf(5, 2)
+        assert_frame_equal(df.loc[:,[]], df.iloc[:, :0])  # vertical empty
+        assert_frame_equal(df.loc[[],:], df.iloc[:0, :])  # horizontal empty
+
+    def test_ix_empty_list_indexer_is_ok(self):
+        raise nose.SkipTest('ix discards columns names')
+        from pandas.util.testing import makeCustomDataframe as mkdf
+        df = mkdf(5, 2)
+        assert_frame_equal(df.ix[:,[]], df.iloc[:, :0])  # vertical empty
+        assert_frame_equal(df.ix[[],:], df.iloc[:0, :])  # horizontal empty
 
 if __name__ == '__main__':
     import nose