Description
-
I have checked that this issue has not already been reported.
-
I have confirmed this bug exists on the latest version of pandas.
-
I have confirmed this bug exists on the master branch of pandas.
Reproducible Example
ser = pd.Series(range(5))
mask = np.array([True, False, True, False, True])
# The following are all equivalent ATM, but only the first makes sense to me
ser[mask] = 10
ser[mask] = np.array([10])
ser[mask] = [10]
ser[mask] = (10,)
# If we try these with loc or iloc these raise
>>> ser.loc[mask] = (10,)
[...]
ValueError: cannot set using a list-like indexer with a different length than the value
>>> ser.iloc[mask] = [10]
[...]
ValueError: cannot set using a list-like indexer with a different length than the value
Issue Description
This behavior occurs because Series.__setitem__
goes through Series._where
in cases where the key is a boolean mask. It then ends up going through Manager.putmask
, which uses np.putmask
semantics (mostly) that repeat/broadcast a listlike value.
AFAICT this repeat/broadcasting makes sense for Series.where
and Series.mask
, but not for Series.__setitem__
. I think this behavior is largely accidental. If we disable this behavior in Series.__setitem__
, 86 tests break. Of these, 84 are tests.series.indexing.test_where.test_downcast
, and the PR (#4195) that introduced that test was about where
, not __setitem__
. The other two tests I tentatively think are breaking because of the particular way I've disabled the broadcasting.
Expected Behavior
ser[mask] = (10,)
should raise.
Installed Versions
Replace this line with the output of pd.show_versions()