From 9299b813f0b89172a73f30ad1f1363f6f17e576f Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 19 Mar 2020 19:39:17 -0700 Subject: [PATCH 1/3] BUG: is_scalar_indexer --- pandas/core/indexers.py | 12 +++++++----- pandas/core/internals/blocks.py | 8 +++----- pandas/tests/indexing/test_indexers.py | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/pandas/core/indexers.py b/pandas/core/indexers.py index 71fd5b6aab821..85d4f26ed05d7 100644 --- a/pandas/core/indexers.py +++ b/pandas/core/indexers.py @@ -65,7 +65,7 @@ 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. @@ -73,10 +73,12 @@ def is_scalar_indexer(indexer, arr_value) -> bool: ------- 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 diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index adeb1ae04a58d..df11c1e3a831c 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -883,7 +883,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 @@ -901,12 +901,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) # set else: diff --git a/pandas/tests/indexing/test_indexers.py b/pandas/tests/indexing/test_indexers.py index 173f33b19f8d5..35c0c06e86099 100644 --- a/pandas/tests/indexing/test_indexers.py +++ b/pandas/tests/indexing/test_indexers.py @@ -1,7 +1,7 @@ # 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(): @@ -9,3 +9,20 @@ def test_length_of_indexer(): 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) From 8d9b66b11e64628805c17d6033ffd0310da480a3 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 20 Mar 2020 08:41:00 -0700 Subject: [PATCH 2/3] update docstring --- pandas/core/indexers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/core/indexers.py b/pandas/core/indexers.py index 85d4f26ed05d7..3d0e3699264a8 100644 --- a/pandas/core/indexers.py +++ b/pandas/core/indexers.py @@ -69,6 +69,12 @@ 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 From c9a40592d2ff0b080086f4b00df3b89c03676490 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 20 Mar 2020 11:36:57 -0700 Subject: [PATCH 3/3] add copy=False --- pandas/core/internals/blocks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 42a7782047da6..ce3c34d33021b 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -895,7 +895,7 @@ def setitem(self, indexer, value): # We are setting _all_ of the array's values, so can cast to new dtype values[indexer] = value - values = values.astype(arr_value.dtype) + values = values.astype(arr_value.dtype, copy=False) # set else: