Skip to content

Commit 270dd26

Browse files
committed
BUG: Bug in loc setting with multiple indexers and a rhs of a Series that needs
broadcasting (GH5206)
1 parent 04dbd55 commit 270dd26

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,8 @@ Bug Fixes
594594
- Bug in comparing duplicate frames (:issue:`4421`) related
595595
- Bug in describe on duplicate frames
596596
- Bug in ``to_datetime`` with a format and ``coerce=True`` not raising (:issue:`5195`)
597+
- Bug in ``loc`` setting with multiple indexers and a rhs of a Series that needs
598+
broadcasting (:issue:`5206`)
597599

598600
pandas 0.12.0
599601
-------------

pandas/core/indexing.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,11 @@ def _align_series(self, indexer, ser):
370370
if isinstance(indexer, tuple):
371371

372372
aligners = [ not _is_null_slice(idx) for idx in indexer ]
373-
single_aligner = sum(aligners) == 1
373+
sum_aligners = sum(aligners)
374+
single_aligner = sum_aligners == 1
374375
is_frame = self.obj.ndim == 2
375376
is_panel = self.obj.ndim >= 3
377+
obj = self.obj
376378

377379
# are we a single alignable value on a non-primary
378380
# dim (e.g. panel: 1,2, or frame: 0) ?
@@ -387,7 +389,15 @@ def _align_series(self, indexer, ser):
387389
elif is_panel:
388390
single_aligner = single_aligner and (aligners[1] or aligners[2])
389391

390-
obj = self.obj
392+
# we have a frame, with multiple indexers on both axes; and a series,
393+
# so need to broadcast (see GH5206)
394+
if sum_aligners == self.ndim and all([ com._is_sequence(_) for _ in indexer ]):
395+
396+
ser = ser.reindex(obj.axes[0][indexer[0].ravel()],copy=True).values
397+
l = len(indexer[1].ravel())
398+
ser = np.tile(ser,l).reshape(l,-1).T
399+
return ser
400+
391401
for i, idx in enumerate(indexer):
392402
ax = obj.axes[i]
393403

@@ -398,6 +408,8 @@ def _align_series(self, indexer, ser):
398408
new_ix = ax[idx]
399409
if not is_list_like(new_ix):
400410
new_ix = Index([new_ix])
411+
else:
412+
new_ix = Index(new_ix.ravel())
401413
if ser.index.equals(new_ix):
402414
return ser.values.copy()
403415
return ser.reindex(new_ix).values

pandas/tests/test_indexing.py

+11
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,17 @@ def test_multi_assign(self):
10371037
df2.ix[mask, cols]= dft.ix[mask, cols].values
10381038
assert_frame_equal(df2,expected)
10391039

1040+
# broadcasting on the rhs is required
1041+
df = DataFrame(dict(A = [1,2,0,0,0],B=[0,0,0,10,11],C=[0,0,0,10,11],D=[3,4,5,6,7]))
1042+
1043+
expected = df.copy()
1044+
mask = expected['A'] == 0
1045+
for col in ['A','B']:
1046+
expected.loc[mask,col] = df['D']
1047+
1048+
df.loc[df['A']==0,['A','B']] = df['D']
1049+
assert_frame_equal(df,expected)
1050+
10401051
def test_ix_assign_column_mixed(self):
10411052
# GH #1142
10421053
df = DataFrame(tm.getSeriesData())

0 commit comments

Comments
 (0)