Skip to content

Commit 8809b04

Browse files
toobazjorisvandenbossche
authored andcommitted
BUG: support for "level=" when reset_index() is called with a single level Index (pandas-dev#16266)
1 parent ba60321 commit 8809b04

File tree

4 files changed

+86
-10
lines changed

4 files changed

+86
-10
lines changed

doc/source/whatsnew/v0.20.2.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Conversion
4242
Indexing
4343
^^^^^^^^
4444

45-
45+
- Bug in ``DataFrame.reset_index(level=)`` with single level index (:issue:`16263`)
4646

4747

4848
I/O

pandas/core/frame.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -3012,12 +3012,12 @@ def _maybe_casted_values(index, labels=None):
30123012
return values
30133013

30143014
new_index = _default_index(len(new_obj))
3015-
if isinstance(self.index, MultiIndex):
3016-
if level is not None:
3017-
if not isinstance(level, (tuple, list)):
3018-
level = [level]
3019-
level = [self.index._get_level_number(lev) for lev in level]
3020-
if len(level) < len(self.index.levels):
3015+
if level is not None:
3016+
if not isinstance(level, (tuple, list)):
3017+
level = [level]
3018+
level = [self.index._get_level_number(lev) for lev in level]
3019+
if isinstance(self.index, MultiIndex):
3020+
if len(level) < self.index.nlevels:
30213021
new_index = self.index.droplevel(level)
30223022

30233023
if not drop:
@@ -3033,6 +3033,8 @@ def _maybe_casted_values(index, labels=None):
30333033

30343034
multi_col = isinstance(self.columns, MultiIndex)
30353035
for i, (lev, lab) in reversed(list(enumerate(to_insert))):
3036+
if not (level is None or i in level):
3037+
continue
30363038
name = names[i]
30373039
if multi_col:
30383040
col_name = (list(name) if isinstance(name, tuple)
@@ -3049,11 +3051,9 @@ def _maybe_casted_values(index, labels=None):
30493051
missing = self.columns.nlevels - len(name_lst)
30503052
name_lst += [col_fill] * missing
30513053
name = tuple(name_lst)
3052-
30533054
# to ndarray and maybe infer different dtype
30543055
level_values = _maybe_casted_values(lev, lab)
3055-
if level is None or i in level:
3056-
new_obj.insert(0, name, level_values)
3056+
new_obj.insert(0, name, level_values)
30573057

30583058
new_obj.index = new_index
30593059
if not inplace:

pandas/tests/frame/test_alter_axes.py

+37
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,43 @@ def test_reset_index(self):
641641
xp = xp.set_index(['B'], append=True)
642642
assert_frame_equal(rs, xp, check_names=False)
643643

644+
def test_reset_index_level(self):
645+
df = pd.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8]],
646+
columns=['A', 'B', 'C', 'D'])
647+
648+
for levels in ['A', 'B'], [0, 1]:
649+
# With MultiIndex
650+
result = df.set_index(['A', 'B']).reset_index(level=levels[0])
651+
tm.assert_frame_equal(result, df.set_index('B'))
652+
653+
result = df.set_index(['A', 'B']).reset_index(level=levels[:1])
654+
tm.assert_frame_equal(result, df.set_index('B'))
655+
656+
result = df.set_index(['A', 'B']).reset_index(level=levels)
657+
tm.assert_frame_equal(result, df)
658+
659+
result = df.set_index(['A', 'B']).reset_index(level=levels,
660+
drop=True)
661+
tm.assert_frame_equal(result, df[['C', 'D']])
662+
663+
# With single-level Index (GH 16263)
664+
result = df.set_index('A').reset_index(level=levels[0])
665+
tm.assert_frame_equal(result, df)
666+
667+
result = df.set_index('A').reset_index(level=levels[:1])
668+
tm.assert_frame_equal(result, df)
669+
670+
result = df.set_index(['A']).reset_index(level=levels[0],
671+
drop=True)
672+
tm.assert_frame_equal(result, df[['B', 'C', 'D']])
673+
674+
# Missing levels - for both MultiIndex and single-level Index:
675+
for idx_lev in ['A', 'B'], ['A']:
676+
with tm.assert_raises_regex(KeyError, 'Level E '):
677+
df.set_index(idx_lev).reset_index(level=['A', 'E'])
678+
with tm.assert_raises_regex(IndexError, 'Too many levels'):
679+
df.set_index(idx_lev).reset_index(level=[0, 1, 2])
680+
644681
def test_reset_index_right_dtype(self):
645682
time = np.arange(0.0, 10, np.sqrt(2) / 2)
646683
s1 = Series((9.81 * time ** 2) / 2,

pandas/tests/series/test_alter_axes.py

+39
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,45 @@ def test_reset_index(self):
141141
tm.assert_index_equal(rs.index, Index(index.get_level_values(1)))
142142
assert isinstance(rs, Series)
143143

144+
def test_reset_index_level(self):
145+
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]],
146+
columns=['A', 'B', 'C'])
147+
148+
for levels in ['A', 'B'], [0, 1]:
149+
# With MultiIndex
150+
s = df.set_index(['A', 'B'])['C']
151+
152+
result = s.reset_index(level=levels[0])
153+
tm.assert_frame_equal(result, df.set_index('B'))
154+
155+
result = s.reset_index(level=levels[:1])
156+
tm.assert_frame_equal(result, df.set_index('B'))
157+
158+
result = s.reset_index(level=levels)
159+
tm.assert_frame_equal(result, df)
160+
161+
result = df.set_index(['A', 'B']).reset_index(level=levels,
162+
drop=True)
163+
tm.assert_frame_equal(result, df[['C']])
164+
165+
with tm.assert_raises_regex(KeyError, 'Level E '):
166+
s.reset_index(level=['A', 'E'])
167+
168+
# With single-level Index
169+
s = df.set_index('A')['B']
170+
171+
result = s.reset_index(level=levels[0])
172+
tm.assert_frame_equal(result, df[['A', 'B']])
173+
174+
result = s.reset_index(level=levels[:1])
175+
tm.assert_frame_equal(result, df[['A', 'B']])
176+
177+
result = s.reset_index(level=levels[0], drop=True)
178+
tm.assert_series_equal(result, df['B'])
179+
180+
with tm.assert_raises_regex(IndexError, 'Too many levels'):
181+
s.reset_index(level=[0, 1, 2])
182+
144183
def test_reset_index_range(self):
145184
# GH 12071
146185
s = pd.Series(range(2), name='A', dtype='int64')

0 commit comments

Comments
 (0)