Skip to content

BUG: is_scalar_indexer #32850

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 5 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions pandas/core/indexers.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,26 @@ def is_list_like_indexer(key) -> bool:
return is_list_like(key) and not (isinstance(key, tuple) and type(key) is not tuple)


def is_scalar_indexer(indexer, arr_value) -> bool:
def is_scalar_indexer(indexer, ndim: int) -> bool:
"""
Return True if we are all scalar indexers.

Parameters
----------
indexer : object
ndim : int
Number of dimensions in the object being indexed.

Returns
-------
bool
"""
if arr_value.ndim == 1:
if not isinstance(indexer, tuple):
indexer = tuple([indexer])
return any(isinstance(idx, np.ndarray) and len(idx) == 0 for idx in indexer)
if isinstance(indexer, tuple):
if len(indexer) == ndim:
return all(
is_integer(x) or (isinstance(x, np.ndarray) and x.ndim == len(x) == 1)
for x in indexer
)
return False


Expand Down
8 changes: 3 additions & 5 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ def setitem(self, indexer, value):
# GH#8669 empty indexers
pass

elif is_scalar_indexer(indexer, arr_value):
elif is_scalar_indexer(indexer, self.ndim):
# setting a single element for each dim and with a rhs that could
# be e.g. a list; see GH#6043
values[indexer] = value
Expand All @@ -892,12 +892,10 @@ def setitem(self, indexer, value):
# if we are an exact match (ex-broadcasting),
# then use the resultant dtype
elif exact_match:
# We are setting _all_ of the array's values, so can cast to new dtype
values[indexer] = value

try:
values = values.astype(arr_value.dtype)
except ValueError:
pass
values = values.astype(arr_value.dtype, copy=False)

# set
else:
Expand Down
19 changes: 18 additions & 1 deletion pandas/tests/indexing/test_indexers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
# Tests aimed at pandas.core.indexers
import numpy as np

from pandas.core.indexers import length_of_indexer
from pandas.core.indexers import is_scalar_indexer, length_of_indexer


def test_length_of_indexer():
arr = np.zeros(4, dtype=bool)
arr[0] = 1
result = length_of_indexer(arr)
assert result == 1


def test_is_scalar_indexer():
indexer = (0, 1)
assert is_scalar_indexer(indexer, 2)
assert not is_scalar_indexer(indexer[0], 2)

indexer = (np.array([2]), 1)
assert is_scalar_indexer(indexer, 2)

indexer = (np.array([2]), np.array([3]))
assert is_scalar_indexer(indexer, 2)

indexer = (np.array([2]), np.array([3, 4]))
assert not is_scalar_indexer(indexer, 2)

assert not is_scalar_indexer(slice(None), 1)