Skip to content

BUG: Cleaner exception when .iloc called with non-integer list #25759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 26, 2019
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ Interval
Indexing
^^^^^^^^

-
- Improved exception message when calling :meth:`DataFrame.iloc` with a list of non-numeric objects (:issue:`25753`).
-
-

Expand Down
9 changes: 7 additions & 2 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from pandas.core.dtypes.common import (
ensure_platform_int, is_float, is_integer, is_integer_dtype, is_iterator,
is_list_like, is_scalar, is_sequence, is_sparse)
is_list_like, is_numeric_dtype, is_scalar, is_sequence, is_sparse)
from pandas.core.dtypes.generic import ABCDataFrame, ABCPanel, ABCSeries
from pandas.core.dtypes.missing import _infer_fill_value, isna

Expand Down Expand Up @@ -2075,10 +2075,15 @@ def _validate_key(self, key, axis):
# so don't treat a tuple as a valid indexer
raise IndexingError('Too many indexers')
elif is_list_like_indexer(key):
# check that the key does not exceed the maximum size of the index
arr = np.array(key)
len_axis = len(self.obj._get_axis(axis))

# check that the key has a numeric dtype
if not is_numeric_dtype(arr.dtype):
raise IndexError(".iloc requires numeric indexers, got "
"{arr}".format(arr=arr))

# check that the key does not exceed the maximum size of the index
if len(arr) and (arr.max() >= len_axis or arr.min() < -len_axis):
raise IndexError("positional indexers are out-of-bounds")
else:
Expand Down
15 changes: 15 additions & 0 deletions pandas/tests/indexing/test_iloc.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ def check(result, expected):
with pytest.raises(IndexError, match=msg):
dfl.iloc[:, 4]

@pytest.mark.parametrize("index,columns", [(np.arange(20), list('ABCDE'))])
@pytest.mark.parametrize("index_vals,column_vals", [
([slice(None), ['A', 'D']]),
(['1', '2'], slice(None)),
([pd.datetime(2019, 1, 1)], slice(None))])
def test_iloc_non_integer_raises(self, index, columns,
index_vals, column_vals):
# GH 25753
df = DataFrame(np.random.randn(len(index), len(columns)),
index=index,
columns=columns)
msg = '.iloc requires numeric indexers, got'
with pytest.raises(IndexError, match=msg):
df.iloc[index_vals, column_vals]

def test_iloc_getitem_int(self):

# integer
Expand Down