Skip to content

Commit 3da053c

Browse files
authored
BUG: fix length_of_indexer with boolean mask (#31897)
1 parent 7b0887c commit 3da053c

File tree

3 files changed

+25
-22
lines changed

3 files changed

+25
-22
lines changed

pandas/core/indexers.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def maybe_convert_indices(indices, n: int):
219219

220220
def length_of_indexer(indexer, target=None) -> int:
221221
"""
222-
Return the length of a single non-tuple indexer which could be a slice.
222+
Return the expected length of target[indexer]
223223
224224
Returns
225225
-------
@@ -245,6 +245,12 @@ def length_of_indexer(indexer, target=None) -> int:
245245
step = -step
246246
return (stop - start + step - 1) // step
247247
elif isinstance(indexer, (ABCSeries, ABCIndexClass, np.ndarray, list)):
248+
if isinstance(indexer, list):
249+
indexer = np.array(indexer)
250+
251+
if indexer.dtype == bool:
252+
# GH#25774
253+
return indexer.sum()
248254
return len(indexer)
249255
elif not is_list_like_indexer(indexer):
250256
return 1

pandas/core/indexing.py

+7-21
Original file line numberDiff line numberDiff line change
@@ -1690,31 +1690,17 @@ def _setitem_with_indexer(self, indexer, value):
16901690

16911691
plane_indexer = tuple([idx]) + indexer[info_axis + 1 :]
16921692
lplane_indexer = length_of_indexer(plane_indexer[0], index)
1693+
# lplane_indexer gives the expected length of obj[idx]
16931694

16941695
# require that we are setting the right number of values that
16951696
# we are indexing
1696-
if (
1697-
is_list_like_indexer(value)
1698-
and np.iterable(value)
1699-
and lplane_indexer != len(value)
1700-
):
1701-
1702-
if len(obj[idx]) != len(value):
1703-
raise ValueError(
1704-
"cannot set using a multi-index "
1705-
"selection indexer with a different "
1706-
"length than the value"
1707-
)
1708-
1709-
# make sure we have an ndarray
1710-
value = getattr(value, "values", value).ravel()
1697+
if is_list_like_indexer(value) and lplane_indexer != len(value):
17111698

1712-
# we can directly set the series here
1713-
obj._consolidate_inplace()
1714-
obj = obj.copy()
1715-
obj._data = obj._data.setitem(indexer=tuple([idx]), value=value)
1716-
self.obj[item] = obj
1717-
return
1699+
raise ValueError(
1700+
"cannot set using a multi-index "
1701+
"selection indexer with a different "
1702+
"length than the value"
1703+
)
17181704

17191705
# non-mi
17201706
else:
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Tests aimed at pandas.core.indexers
2+
import numpy as np
3+
4+
from pandas.core.indexers import length_of_indexer
5+
6+
7+
def test_length_of_indexer():
8+
arr = np.zeros(4, dtype=bool)
9+
arr[0] = 1
10+
result = length_of_indexer(arr)
11+
assert result == 1

0 commit comments

Comments
 (0)