Skip to content

Commit 9b024b5

Browse files
committed
Merge pull request #8480 from behzadnouri/align-mi
BUG: sub-frame assignment of a multi-index frame breaks alignment
2 parents 6d3803d + 70e3ff3 commit 9b024b5

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

doc/source/v0.15.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1066,3 +1066,4 @@ Bug Fixes
10661066
- Bug in ``NDFrame.loc`` indexing when row/column names were lost when target was a list/ndarray (:issue:`6552`)
10671067
- Regression in ``NDFrame.loc`` indexing when rows/columns were converted to Float64Index if target was an empty list/ndarray (:issue:`7774`)
10681068
- Bug in Series that allows it to be indexed by a DataFrame which has unexpected results. Such indexing is no longer permitted (:issue:`8444`)
1069+
- Bug in item assignment of a DataFrame with multi-index columns where right-hand-side columns were not aligned (:issue:`7655`)

pandas/core/frame.py

+9
Original file line numberDiff line numberDiff line change
@@ -2194,6 +2194,15 @@ def reindexer(value):
21942194
value = reindexer(value)
21952195

21962196
elif isinstance(value, DataFrame):
2197+
# align right-hand-side columns if self.columns
2198+
# is multi-index and self[key] is a sub-frame
2199+
if isinstance(self.columns, MultiIndex) and key in self.columns:
2200+
loc = self.columns.get_loc(key)
2201+
if isinstance(loc, (slice, Series, np.ndarray, Index)):
2202+
cols = _maybe_droplevels(self.columns[loc], key)
2203+
if len(cols) and not cols.equals(value.columns):
2204+
value = value.reindex_axis(cols, axis=1)
2205+
# now align rows
21972206
value = reindexer(value).T
21982207

21992208
elif isinstance(value, Categorical):

pandas/tests/test_frame.py

+25
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,31 @@ def test_setitem_list_of_tuples(self):
224224
expected = Series(tuples, index=self.frame.index)
225225
assert_series_equal(result, expected)
226226

227+
def test_setitem_mulit_index(self):
228+
# GH7655, test that assigning to a sub-frame of a frame
229+
# with multi-index columns aligns both rows and columns
230+
it = ['jim', 'joe', 'jolie'], ['first', 'last'], \
231+
['left', 'center', 'right']
232+
233+
cols = MultiIndex.from_product(it)
234+
index = pd.date_range('20141006',periods=20)
235+
vals = np.random.randint(1, 1000, (len(index), len(cols)))
236+
df = pd.DataFrame(vals, columns=cols, index=index)
237+
238+
i, j = df.index.values.copy(), it[-1][:]
239+
240+
np.random.shuffle(i)
241+
df['jim'] = df['jolie'].loc[i, ::-1]
242+
assert_frame_equal(df['jim'], df['jolie'])
243+
244+
np.random.shuffle(j)
245+
df[('joe', 'first')] = df[('jolie', 'last')].loc[i, j]
246+
assert_frame_equal(df[('joe', 'first')], df[('jolie', 'last')])
247+
248+
np.random.shuffle(j)
249+
df[('joe', 'last')] = df[('jolie', 'first')].loc[i, j]
250+
assert_frame_equal(df[('joe', 'last')], df[('jolie', 'first')])
251+
227252
def test_getitem_boolean(self):
228253
# boolean indexing
229254
d = self.tsframe.index[10]

0 commit comments

Comments
 (0)