ENH: Reset MultiIndex at specific column levels
State: closed

- [x] tests added / passed
- [ ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry

**Code Sample**
```python
>>> index = pd.MultiIndex.from_tuples([('bird', 'falcon'), ('bird', 'parrot'), ('mammal', 'lion'), ('mammal', 'monkey')], names=['class', 'name'])
>>> columns = pd.MultiIndex.from_tuples([('speed', 'max'), ('species', 'type')])
>>> df = pd.DataFrame([(389.0, 'fly'), ( 24.0, 'fly'), ( 80.5, 'run'), (np.nan, 'jump')], index=index, columns=columns)
>>> df
```
```console
               speed species
                 max    type
class  name
bird   falcon  389.0     fly
       parrot   24.0     fly
mammal lion     80.5     run
       monkey    NaN    jump
```
```python
>>> df.reset_index(level=['class', 'name'], col_level=[1, 0], col_fill=['genus', 'pet'])
```
```console
    genus    name  speed species
    class     pet    max    type
0    bird  falcon  389.0     fly
1    bird  parrot   24.0     fly
2  mammal    lion   80.5     run
3  mammal  monkey    NaN    jump
```
**Explanation**

For DataFrames having MultiIndex Index and MultiIndex columns,
the `col_level` parameter can also accept a list / tuple so that each
index level's name can be mapped to a specific column level.

if not enough `col_level` / `col_fill` values are given, then the last 
given value maps to the remaining levels.

Labels:
name: Reshaping
description: Concat, Merge/Join, Stack/Unstack, Explode

Comments:
Hello @ryanreh99! Thanks for updating this PR. We checked the lines you've touched for [PEP 8](https://www.python.org/dev/peps/pep-0008) issues, and found:





There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers: 

##### Comment last updated at 2019-06-23 20:37:52 UTC
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=h1) Report
> Merging [#26978](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/b9b081dc6b510c8290ded12fe751b1216843527e?src=pr&el=desc) will **decrease** coverage by `50.15%`.
> The diff coverage is `28.57%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/26978/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=tree)

```diff
@@             Coverage Diff             @@
##           master   #26978       +/-   ##
===========================================
- Coverage   91.97%   41.82%   -50.16%     
===========================================
  Files         180      180               
  Lines       50756    50779       +23     
===========================================
- Hits        46685    21238    -25447     
- Misses       4071    29541    +25470
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `?` | |
| #single | `41.82% <28.57%> (-0.09%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `34.99% <28.57%> (-62.02%)` | :arrow_down: |
| [pandas/io/formats/latex.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2Zvcm1hdHMvbGF0ZXgucHk=) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/io/gcs.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2djcy5weQ==) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/io/sas/sas\_constants.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3Nhcy9zYXNfY29uc3RhbnRzLnB5) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/core/groupby/categorical.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ3JvdXBieS9jYXRlZ29yaWNhbC5weQ==) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/tseries/plotting.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvcGxvdHRpbmcucHk=) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/tseries/converter.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvY29udmVydGVyLnB5) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/io/s3.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3MzLnB5) | `0% <0%> (-100%)` | :arrow_down: |
| [pandas/io/formats/html.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2Zvcm1hdHMvaHRtbC5weQ==) | `0% <0%> (-99.37%)` | :arrow_down: |
| [pandas/io/sas/sas7bdat.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3Nhcy9zYXM3YmRhdC5weQ==) | `0% <0%> (-91.16%)` | :arrow_down: |
| ... and [133 more](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=footer). Last update [b9b081d...96ea98b](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=h1) Report
> Merging [#26978](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/cf74b0272af2e13e5b9ce40c8bf42df750ddc560?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `97.22%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/26978/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #26978      +/-   ##
==========================================
- Coverage   91.99%   91.99%   -0.01%     
==========================================
  Files         180      180              
  Lines       50774    50794      +20     
==========================================
+ Hits        46711    46726      +15     
- Misses       4063     4068       +5
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.63% <97.22%> (ø)` | :arrow_up: |
| #single | `41.83% <38.88%> (-0.09%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `96.87% <97.22%> (-0.14%)` | :arrow_down: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/26978/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `88.88% <0%> (-11.12%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=footer). Last update [cf74b02...d1e4cc6](https://codecov.io/gh/pandas-dev/pandas/pull/26978?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

IIUC this is already possible via

``df.reset_index().set_index(list_of_levels_that_I_want_to_keep)``

?
@jreback `df.reset_index().set_index()` sets all the index names to the same column level.
This PL allows the user to set the index names at different column levels.

In this function if we can set multiple index names to a single column level I guess we should be able to decide which index name goes to which position?
@TomAugspurger please tell me if the changes seem acceptable.
Sorry, I'm still having a trouble understanding the example.
btw i had a related question, 
```python
>>> index = pd.MultiIndex.from_product([('foo', 'bar'), ('one', 'two')], names=['first', 'second'])
>>> df = pd.DataFrame(range(4), index = index, columns = ['ok'])
>>> df
```
```console
              ok
first second
foo   one      0
      two      1
bar   one      2
      two      3
```
currently `df.reset_index([0, 1])` and `df.reset_index([1, 0])` gives the same result

But `df.reset_index([0, 1])` giving 
```console
  first second  ok
0   foo    one   0
1   foo    two   1
2   bar    one   2
3   bar    two   3
```
and `df.reset_index([1, 0])` giving 
```console
  second first  ok
0    one   foo   0
1    two   foo   1
2    one   bar   2
3    two   bar   3
```
be something you would consider?
closing in favor of discussion at #26742