Repository: pandas-dev/pandas

Issue:
Series.reset_index(level_name, drop=True) accepts invalid name when index is flat
#### Code Sample, a copy-pastable example if possible

```python
In [2]: s = pd.Series(range(4))

In [3]: s.reset_index('wrong', drop=True)
Out[3]: 
0    0
1    1
2    2
3    3
dtype: int64

In [4]: s.reset_index('wrong')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-a7b872dfe0cf> in <module>()
----> 1 s.reset_index('wrong')

~/nobackup/repo/pandas/pandas/core/series.py in reset_index(self, level, drop, name, inplace)
   1215         else:
   1216             df = self.to_frame(name)
-> 1217             return df.reset_index(level=level, drop=drop)
   1218 
   1219     def __unicode__(self):

~/nobackup/repo/pandas/pandas/core/frame.py in reset_index(self, level, drop, inplace, col_level, col_fill)
   4098             if not isinstance(level, (tuple, list)):
   4099                 level = [level]
-> 4100             level = [self.index._get_level_number(lev) for lev in level]
   4101             if isinstance(self.index, MultiIndex):
   4102                 if len(level) < self.index.nlevels:

~/nobackup/repo/pandas/pandas/core/frame.py in <listcomp>(.0)
   4098             if not isinstance(level, (tuple, list)):
   4099                 level = [level]
-> 4100             level = [self.index._get_level_number(lev) for lev in level]
   4101             if isinstance(self.index, MultiIndex):
   4102                 if len(level) < self.index.nlevels:

~/nobackup/repo/pandas/pandas/core/indexes/base.py in _get_level_number(self, level)
   1944 
   1945     def _get_level_number(self, level):
-> 1946         self._validate_index_level(level)
   1947         return 0
   1948 

~/nobackup/repo/pandas/pandas/core/indexes/base.py in _validate_index_level(self, level)
   1941         elif level != self.name:
   1942             raise KeyError('Level %s must be same as name (%s)' %
-> 1943                            (level, self.name))
   1944 
   1945     def _get_level_number(self, level):

KeyError: 'Level wrong must be same as name (None)'

In [5]: s = pd.Series(range(4), index=pd.MultiIndex.from_product([[1, 2]]*2))

In [6]: s.reset_index('wrong', drop=True)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/nobackup/repo/pandas/pandas/core/indexes/multi.py in _get_level_number(self, level)
    775                                  'level number' % level)
--> 776             level = self.names.index(level)
    777         except ValueError:

ValueError: 'wrong' is not in list

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-6-e0d143f488d8> in <module>()
----> 1 s.reset_index('wrong', drop=True)

~/nobackup/repo/pandas/pandas/core/series.py in reset_index(self, level, drop, name, inplace)
   1199                 if not isinstance(level, (tuple, list)):
   1200                     level = [level]
-> 1201                 level = [self.index._get_level_number(lev) for lev in level]
   1202                 if len(level) < len(self.index.levels):
   1203                     new_index = self.index.droplevel(level)

~/nobackup/repo/pandas/pandas/core/series.py in <listcomp>(.0)
   1199                 if not isinstance(level, (tuple, list)):
   1200                     level = [level]
-> 1201                 level = [self.index._get_level_number(lev) for lev in level]
   1202                 if len(level) < len(self.index.levels):
   1203                     new_index = self.index.droplevel(level)

~/nobackup/repo/pandas/pandas/core/indexes/multi.py in _get_level_number(self, level)
    777         except ValueError:
    778             if not isinstance(level, int):
--> 779                 raise KeyError('Level %s not found' % str(level))
    780             elif level < 0:
    781                 level += self.nlevels

KeyError: 'Level wrong not found'
```

#### Problem description

``In [3]:`` should raise too.

#### Expected Output

Same as ``In [4]:``

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.5.3.final.0
python-bits: 64
OS: Linux
OS-release: 4.9.0-6-amd64
machine: x86_64
processor: 
byteorder: little
LC_ALL: None
LANG: it_IT.UTF-8
LOCALE: it_IT.UTF-8

pandas: 0.23.0.dev0+825.ga3facfc55
pytest: 3.5.0
pip: 9.0.1
setuptools: 39.0.1
Cython: 0.25.2
numpy: 1.14.1
scipy: 0.19.0
pyarrow: None
xarray: None
IPython: 6.2.1
sphinx: 1.5.6
patsy: 0.5.0
dateutil: 2.7.0
pytz: 2017.2
blosc: None
bottleneck: 1.2.0dev
tables: 3.3.0
numexpr: 2.6.1
feather: 0.3.1
matplotlib: 2.0.0
openpyxl: 2.3.0
xlrd: 1.0.0
xlwt: 1.3.0
xlsxwriter: 0.9.6
lxml: 4.1.1
bs4: 4.5.3
html5lib: 0.999999999
sqlalchemy: 1.0.15
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: 0.2.1


</details>



Discussion:
Can I try to deal with this one as my first issue?
> Can I try to deal with this one as my first issue?

Sure!

Notice the following should also raise:

``` python
In [2]: s = pd.Series(range(4), name='valid')

In [3]: s.reset_index(['valid', 'valid'], drop=True)
Out[3]: 
0    0
1    1
2    2
3    3
Name: valid, dtype: int64

```
... and bonus points if the following raises too (but leaving it aside for the moment is also fine):
``` python
In [2]: s = pd.Series(range(4))

In [3]: s.reset_index([None, None])
Out[3]: 
   index  0
0      0  0
1      1  1
2      2  2
3      3  3
```

Hi, I'm a beginner and would like to contribute as my first bug fix. I'm not quite certain I understand the bug. Could you please explain?
@rahulgo this bug is probably already being worked on by @misupova : I suggest you pick another one (still marked as [good first issue](https://github.com/pandas-dev/pandas/labels/good%20first%20issue) ), possibly one for which you have a better understanding

Resolving patch:
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -1195,12 +1195,13 @@ def reset_index(self, level=None, drop=False, name=None, inplace=False):
         inplace = validate_bool_kwarg(inplace, 'inplace')
         if drop:
             new_index = com._default_index(len(self))
-            if level is not None and isinstance(self.index, MultiIndex):
+            if level is not None:
                 if not isinstance(level, (tuple, list)):
                     level = [level]
                 level = [self.index._get_level_number(lev) for lev in level]
-                if len(level) < len(self.index.levels):
-                    new_index = self.index.droplevel(level)
+                if isinstance(self.index, MultiIndex):
+                    if len(level) < self.index.nlevels:
+                        new_index = self.index.droplevel(level)
 
             if inplace:
                 self.index = new_index


Test patch:
diff --git a/pandas/tests/series/test_alter_axes.py b/pandas/tests/series/test_alter_axes.py
--- a/pandas/tests/series/test_alter_axes.py
+++ b/pandas/tests/series/test_alter_axes.py
@@ -188,6 +188,11 @@ def test_reset_index_level(self):
             with tm.assert_raises_regex(IndexError, 'Too many levels'):
                 s.reset_index(level=[0, 1, 2])
 
+        # Check that .reset_index([],drop=True) doesn't fail
+        result = pd.Series(range(4)).reset_index([], drop=True)
+        expected = pd.Series(range(4))
+        assert_series_equal(result, expected)
+
     def test_reset_index_range(self):
         # GH 12071
         s = pd.Series(range(2), name='A', dtype='int64')
@@ -275,3 +280,18 @@ def test_set_axis_prior_to_deprecation_signature(self):
             with tm.assert_produces_warning(FutureWarning):
                 result = s.set_axis(0, list('abcd'), inplace=False)
             tm.assert_series_equal(result, expected)
+
+    def test_reset_index_drop_errors(self):
+        #  GH 20925
+
+        # KeyError raised for series index when passed level name is missing
+        s = pd.Series(range(4))
+        with tm.assert_raises_regex(KeyError, 'must be same as name'):
+            s.reset_index('wrong', drop=True)
+        with tm.assert_raises_regex(KeyError, 'must be same as name'):
+            s.reset_index('wrong')
+
+        # KeyError raised for series when level to be dropped is missing
+        s = pd.Series(range(4), index=pd.MultiIndex.from_product([[1, 2]] * 2))
+        with tm.assert_raises_regex(KeyError, 'not found'):
+            s.reset_index('wrong', drop=True)