Skip to content

Commit 4fdd43b

Browse files
jbrockmendelroberthdevries
authored andcommitted
CLN: simplify _setitem_with_indexer (pandas-dev#31887)
1 parent a712c29 commit 4fdd43b

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

pandas/core/indexing.py

+27-22
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,17 @@ def _convert_to_indexer(self, key, axis: int, is_setter: bool = False):
15641564
# -------------------------------------------------------------------
15651565

15661566
def _setitem_with_indexer(self, indexer, value):
1567+
"""
1568+
_setitem_with_indexer is for setting values on a Series/DataFrame
1569+
using positional indexers.
1570+
1571+
If the relevant keys are not present, the Series/DataFrame may be
1572+
expanded.
1573+
1574+
This method is currently broken when dealing with non-unique Indexes,
1575+
since it goes from positional indexers back to labels when calling
1576+
BlockManager methods, see GH#12991, GH#22046, GH#15686.
1577+
"""
15671578

15681579
# also has the side effect of consolidating in-place
15691580
from pandas import Series
@@ -1678,24 +1689,19 @@ def _setitem_with_indexer(self, indexer, value):
16781689
info_idx = [info_idx]
16791690
labels = item_labels[info_idx]
16801691

1681-
# if we have a partial multiindex, then need to adjust the plane
1682-
# indexer here
1683-
if len(labels) == 1 and isinstance(
1684-
self.obj[labels[0]].axes[0], ABCMultiIndex
1685-
):
1692+
if len(labels) == 1:
1693+
# We can operate on a single column
16861694
item = labels[0]
1687-
obj = self.obj[item]
1688-
index = obj.index
1689-
idx = indexer[:info_axis][0]
1695+
idx = indexer[0]
16901696

1691-
plane_indexer = tuple([idx]) + indexer[info_axis + 1 :]
1692-
lplane_indexer = length_of_indexer(plane_indexer[0], index)
1697+
plane_indexer = tuple([idx])
1698+
lplane_indexer = length_of_indexer(plane_indexer[0], self.obj.index)
16931699
# lplane_indexer gives the expected length of obj[idx]
16941700

16951701
# require that we are setting the right number of values that
16961702
# we are indexing
1697-
if is_list_like_indexer(value) and lplane_indexer != len(value):
1698-
1703+
if is_list_like_indexer(value) and 0 != lplane_indexer != len(value):
1704+
# Exclude zero-len for e.g. boolean masking that is all-false
16991705
raise ValueError(
17001706
"cannot set using a multi-index "
17011707
"selection indexer with a different "
@@ -1704,12 +1710,11 @@ def _setitem_with_indexer(self, indexer, value):
17041710

17051711
# non-mi
17061712
else:
1707-
plane_indexer = indexer[:info_axis] + indexer[info_axis + 1 :]
1708-
plane_axis = self.obj.axes[:info_axis][0]
1709-
lplane_indexer = length_of_indexer(plane_indexer[0], plane_axis)
1713+
plane_indexer = indexer[:1]
1714+
lplane_indexer = length_of_indexer(plane_indexer[0], self.obj.index)
17101715

17111716
def setter(item, v):
1712-
s = self.obj[item]
1717+
ser = self.obj[item]
17131718
pi = plane_indexer[0] if lplane_indexer == 1 else plane_indexer
17141719

17151720
# perform the equivalent of a setitem on the info axis
@@ -1721,16 +1726,16 @@ def setter(item, v):
17211726
com.is_null_slice(idx) or com.is_full_slice(idx, len(self.obj))
17221727
for idx in pi
17231728
):
1724-
s = v
1729+
ser = v
17251730
else:
17261731
# set the item, possibly having a dtype change
1727-
s._consolidate_inplace()
1728-
s = s.copy()
1729-
s._data = s._data.setitem(indexer=pi, value=v)
1730-
s._maybe_update_cacher(clear=True)
1732+
ser._consolidate_inplace()
1733+
ser = ser.copy()
1734+
ser._data = ser._data.setitem(indexer=pi, value=v)
1735+
ser._maybe_update_cacher(clear=True)
17311736

17321737
# reset the sliced object if unique
1733-
self.obj[item] = s
1738+
self.obj[item] = ser
17341739

17351740
# we need an iterable, with a ndim of at least 1
17361741
# eg. don't pass through np.array(0)

0 commit comments

Comments
 (0)