From 30987127ebef6748aa54742723ca92f1dd5fc15b Mon Sep 17 00:00:00 2001 From: Brock Date: Fri, 30 Oct 2020 12:20:17 -0700 Subject: [PATCH] REF: _setitem_with_indexer_split_path --- pandas/core/indexing.py | 142 ++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index e376f930c8c63..3cb9cba01da48 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -1625,94 +1625,94 @@ def _setitem_with_indexer(self, indexer, value): self._setitem_with_indexer_missing(indexer, value) return - # set - item_labels = self.obj._get_axis(info_axis) - # align and set the values if take_split_path: # We have to operate column-wise + self._setitem_with_indexer_split_path(indexer, value) + else: + self._setitem_single_block(indexer, value) - # Above we only set take_split_path to True for 2D cases - assert self.ndim == 2 - assert info_axis == 1 + def _setitem_with_indexer_split_path(self, indexer, value): + """ + Setitem column-wise. + """ + # Above we only set take_split_path to True for 2D cases + assert self.ndim == 2 - if not isinstance(indexer, tuple): - indexer = _tuplify(self.ndim, indexer) + if not isinstance(indexer, tuple): + indexer = _tuplify(self.ndim, indexer) - if isinstance(value, ABCSeries): - value = self._align_series(indexer, value) + if isinstance(value, ABCSeries): + value = self._align_series(indexer, value) - info_idx = indexer[info_axis] - if is_integer(info_idx): - info_idx = [info_idx] - labels = item_labels[info_idx] + info_idx = indexer[1] + if is_integer(info_idx): + info_idx = [info_idx] + labels = self.obj.columns[info_idx] - # Ensure we have something we can iterate over - ilocs = self._ensure_iterable_column_indexer(indexer[1]) + # Ensure we have something we can iterate over + ilocs = self._ensure_iterable_column_indexer(indexer[1]) - plane_indexer = indexer[:1] - lplane_indexer = length_of_indexer(plane_indexer[0], self.obj.index) - # lplane_indexer gives the expected length of obj[indexer[0]] + plane_indexer = indexer[:1] + lplane_indexer = length_of_indexer(plane_indexer[0], self.obj.index) + # lplane_indexer gives the expected length of obj[indexer[0]] - if len(labels) == 1: - # We can operate on a single column + if len(labels) == 1: + # We can operate on a single column - # require that we are setting the right number of values that - # we are indexing - if is_list_like_indexer(value) and 0 != lplane_indexer != len(value): - # Exclude zero-len for e.g. boolean masking that is all-false - raise ValueError( - "cannot set using a multi-index " - "selection indexer with a different " - "length than the value" - ) - - # we need an iterable, with a ndim of at least 1 - # eg. don't pass through np.array(0) - if is_list_like_indexer(value) and getattr(value, "ndim", 1) > 0: - - # we have an equal len Frame - if isinstance(value, ABCDataFrame): - self._setitem_with_indexer_frame_value(indexer, value) - - # we have an equal len ndarray/convertible to our labels - # hasattr first, to avoid coercing to ndarray without reason. - # But we may be relying on the ndarray coercion to check ndim. - # Why not just convert to an ndarray earlier on if needed? - elif np.ndim(value) == 2: - self._setitem_with_indexer_2d_value(indexer, value) - - elif ( - len(labels) == 1 - and lplane_indexer == len(value) - and not is_scalar(plane_indexer[0]) - ): - # we have an equal len list/ndarray - # We only get here with len(labels) == len(ilocs) == 1 - self._setitem_single_column(ilocs[0], value, plane_indexer) + # require that we are setting the right number of values that + # we are indexing + if is_list_like_indexer(value) and 0 != lplane_indexer != len(value): + # Exclude zero-len for e.g. boolean masking that is all-false + raise ValueError( + "cannot set using a multi-index " + "selection indexer with a different " + "length than the value" + ) - elif lplane_indexer == 0 and len(value) == len(self.obj.index): - # We get here in one case via .loc with a all-False mask - pass + # we need an iterable, with a ndim of at least 1 + # eg. don't pass through np.array(0) + if is_list_like_indexer(value) and getattr(value, "ndim", 1) > 0: + + # we have an equal len Frame + if isinstance(value, ABCDataFrame): + self._setitem_with_indexer_frame_value(indexer, value) + + # we have an equal len ndarray/convertible to our labels + # hasattr first, to avoid coercing to ndarray without reason. + # But we may be relying on the ndarray coercion to check ndim. + # Why not just convert to an ndarray earlier on if needed? + elif np.ndim(value) == 2: + self._setitem_with_indexer_2d_value(indexer, value) + + elif ( + len(labels) == 1 + and lplane_indexer == len(value) + and not is_scalar(plane_indexer[0]) + ): + # we have an equal len list/ndarray + # We only get here with len(labels) == len(ilocs) == 1 + self._setitem_single_column(ilocs[0], value, plane_indexer) - else: - # per-label values - if len(ilocs) != len(value): - raise ValueError( - "Must have equal len keys and value " - "when setting with an iterable" - ) + elif lplane_indexer == 0 and len(value) == len(self.obj.index): + # We get here in one case via .loc with a all-False mask + pass - for loc, v in zip(ilocs, value): - self._setitem_single_column(loc, v, plane_indexer) else: + # per-label values + if len(ilocs) != len(value): + raise ValueError( + "Must have equal len keys and value " + "when setting with an iterable" + ) - # scalar value - for loc in ilocs: - self._setitem_single_column(loc, value, plane_indexer) - + for loc, v in zip(ilocs, value): + self._setitem_single_column(loc, v, plane_indexer) else: - self._setitem_single_block(indexer, value) + + # scalar value + for loc in ilocs: + self._setitem_single_column(loc, value, plane_indexer) def _setitem_with_indexer_2d_value(self, indexer, value): # We get here with np.ndim(value) == 2, excluding DataFrame,