Skip to content

Commit 3f34461

Browse files
author
Si Wei How
committed
Fix code to handle multi-dimensional index properly
1 parent 07801be commit 3f34461

File tree

4 files changed

+46
-35
lines changed

4 files changed

+46
-35
lines changed

doc/source/whatsnew/v0.25.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ Indexing
597597
- Bug in which :meth:`DataFrame.to_csv` caused a segfault for a reindexed data frame, when the indices were single-level :class:`MultiIndex` (:issue:`26303`).
598598
- Fixed bug where assigning a :class:`arrays.PandasArray` to a :class:`pandas.core.frame.DataFrame` would raise error (:issue:`26390`)
599599
- Allow keyword arguments for callable local reference used in the :method:`DataFrame.query` string (:issue:`26426`)
600-
- Bug in assignment to multiple columns of a `DataFrame` when some of the columns do not exist (:issue:`13658`)
600+
- Bug in assignment to multiple columns of a :class:`DataFrame` when some of the columns do not exist (:issue:`13658`)
601601

602602

603603
Missing

pandas/core/indexing.py

+15-11
Original file line numberDiff line numberDiff line change
@@ -1299,17 +1299,21 @@ def _convert_to_indexer(self, obj, axis=None, is_setter=False,
12991299
inds, = obj.nonzero()
13001300
return inds
13011301
else:
1302-
# allow missing columns when setting
1303-
if is_setter and axis == 1:
1304-
return [
1305-
self._convert_to_indexer(k, axis=axis,
1306-
is_setter=is_setter,
1307-
raise_missing=raise_missing)
1308-
for k in obj]
1309-
# When setting, missing keys are not allowed, even with .loc:
1310-
kwargs = {'raise_missing': True if is_setter else
1311-
raise_missing}
1312-
return self._get_listlike_indexer(obj, axis, **kwargs)[1]
1302+
try:
1303+
# When setting, missing keys are not allowed, even with
1304+
# .loc:
1305+
kwargs = {'raise_missing': True if is_setter else
1306+
raise_missing}
1307+
return self._get_listlike_indexer(obj, axis, **kwargs)[1]
1308+
except KeyError:
1309+
# allow missing columns when setting
1310+
if is_setter and axis == 1:
1311+
return [
1312+
self._convert_to_indexer(
1313+
k, axis=axis, is_setter=is_setter,
1314+
raise_missing=raise_missing)
1315+
for k in obj]
1316+
raise
13131317
else:
13141318
try:
13151319
return labels.get_loc(obj)

pandas/tests/frame/test_indexing.py

+26-23
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
from pandas.tests.frame.common import TestData
1919
import pandas.util.testing as tm
2020
from pandas.util.testing import (
21-
assert_almost_equal, assert_frame_equal, assert_index_equal,
22-
assert_numpy_array_equal, assert_series_equal)
21+
assert_almost_equal, assert_frame_equal, assert_series_equal)
2322

2423
from pandas.tseries.offsets import BDay
2524

@@ -187,37 +186,41 @@ def test_setitem_list_of_tuples(self):
187186
assert_series_equal(result, expected)
188187

189188
def test_setitem_list_all_missing_columns_scalar(self):
190-
df = self.frame.copy()
191-
df[['E', 'F']] = 1
192-
df2 = self.frame.copy()
193-
df2['E'] = 1
194-
df2['F'] = 1
195-
assert_frame_equal(df, df2)
189+
# GH 26534
190+
result = self.frame.copy()
191+
result[['E', 'F']] = 1
192+
expected = self.frame.copy()
193+
expected['E'] = 1
194+
expected['F'] = 1
195+
assert_frame_equal(result, expected)
196196

197197
def test_setitem_list_some_missing_columns_list(self):
198-
df = self.frame.copy()
199-
df[['A', 'E']] = [1, 2]
200-
df2 = self.frame.copy()
201-
df2['A'] = 1
202-
df2['E'] = 2
203-
assert_frame_equal(df, df2)
198+
# GH 26534
199+
result = self.frame.copy()
200+
result[['A', 'E']] = [1, 2]
201+
expected = self.frame.copy()
202+
expected['A'] = 1
203+
expected['E'] = 2
204+
assert_frame_equal(result, expected)
204205

205206
def test_setitem_list_some_missing_columns_dataframe(self):
206-
df = self.frame.copy()
207-
df[['A', 'E']] = self.frame[['B', 'C']]
208-
df2 = self.frame.copy()
209-
df2['A'] = self.frame['B']
210-
df2['E'] = self.frame['C']
211-
assert_frame_equal(df, df2)
207+
# GH 26534
208+
result = self.frame.copy()
209+
result[['A', 'E']] = self.frame[['B', 'C']]
210+
expected = self.frame.copy()
211+
expected['A'] = self.frame['B']
212+
expected['E'] = self.frame['C']
213+
assert_frame_equal(result, expected)
212214

213215
def test_setitem_list_some_missing_columns_2dlist(self):
214-
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['A', 'B'])
215-
df[['B', 'C', 'D']] = [[7, 8, 9], [10, 11, 12], [13, 14, 15]]
216+
# GH 26534
217+
result = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['A', 'B'])
218+
result[['B', 'C', 'D']] = [[7, 8, 9], [10, 11, 12], [13, 14, 15]]
216219
expected = pd.DataFrame([[1, 7, 8, 9],
217220
[3, 10, 11, 12],
218221
[5, 13, 14, 15]],
219222
columns=['A', 'B', 'C', 'D'])
220-
tm.assert_frame_equal(df, expected)
223+
tm.assert_frame_equal(result, expected)
221224

222225
def test_setitem_mulit_index(self):
223226
# GH7655, test that assigning to a sub-frame of a frame

pandas/tests/indexing/test_loc.py

+4
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ def test_loc_setitem_with_scalar_index(self, indexer, value):
539539
assert is_scalar(result) and result == 'Z'
540540

541541
def test_loc_setitem_missing_columns_scalar_index_list_value(self):
542+
# GH 26534
542543
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['A', 'B'])
543544
df.loc[1, ['C', 'D']] = [7, 8]
544545
expected = pd.DataFrame([[1, 2, np.nan, np.nan],
@@ -548,6 +549,7 @@ def test_loc_setitem_missing_columns_scalar_index_list_value(self):
548549
tm.assert_frame_equal(df, expected)
549550

550551
def test_loc_setitem_missing_columns_full_index_dataframe_value(self):
552+
# GH 26534
551553
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['A', 'B'])
552554
df2 = pd.DataFrame([[7, 8], [9, 10], [11, 12]], columns=['A', 'C'])
553555
df.loc[:, ['A', 'C']] = df2
@@ -556,6 +558,7 @@ def test_loc_setitem_missing_columns_full_index_dataframe_value(self):
556558
tm.assert_frame_equal(df, expected)
557559

558560
def test_loc_setitem_missing_columns_list_index_scalar_value(self):
561+
# GH 26534
559562
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['A', 'B'])
560563
df.loc[[0, 2], ['B', 'C', 'D']] = 9
561564
expected = pd.DataFrame([[1, 9, 9, 9],
@@ -565,6 +568,7 @@ def test_loc_setitem_missing_columns_list_index_scalar_value(self):
565568
tm.assert_frame_equal(df, expected)
566569

567570
def test_loc_setitem_missing_columns_range_index_2dlist_value(self):
571+
# GH 26534
568572
df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], columns=['A', 'B'])
569573
df.loc[1:3, ['B', 'C', 'D']] = [[7, 8, 9], [10, 11, 12]]
570574
expected = pd.DataFrame([[1, 2, np.nan, np.nan],

0 commit comments

Comments
 (0)