ENH: Support sorting frames by a combo of columns and index levels (GH 14353)
State: closed

This PR implements the changes proposed in #14353. @jorisvandenbossche 

- [x] closes #14353
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry
- [x] Rework to use utility methods introduced in #17484 after it is merged


Labels:
name: Enhancement
name: API Design

Comments:
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@36dadd7`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `93.33%`.

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

```diff
@@            Coverage Diff            @@
##             master   #17361   +/-   ##
=========================================
  Coverage          ?   91.02%           
=========================================
  Files             ?      162           
  Lines             ?    49574           
  Branches          ?        0           
=========================================
  Hits              ?    45123           
  Misses            ?     4451           
  Partials          ?        0
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `88.8% <93.33%> (?)` | |
| #single | `40.24% <6.66%> (?)` | |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/generic.py](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ2VuZXJpYy5weQ==) | `91.99% <ø> (ø)` | |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.68% <93.33%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17361?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/17361?src=pr&el=footer). Last update [36dadd7...10b4e24](https://codecov.io/gh/pandas-dev/pandas/pull/17361?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/17361?src=pr&el=h1) Report
> Merging [#17361](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/c19bdc98fa3f856e2e6b3495bbab88b587801987?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `100%`.

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

```diff
@@            Coverage Diff             @@
##           master   #17361      +/-   ##
==========================================
- Coverage   91.57%   91.57%   -0.01%     
==========================================
  Files         150      150              
  Lines       48941    48940       -1     
==========================================
- Hits        44817    44816       -1     
  Misses       4124     4124
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.93% <100%> (-0.01%)` | :arrow_down: |
| #single | `41.75% <12.5%> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/17361/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.62% <100%> (-0.01%)` | :arrow_down: |
| [pandas/core/groupby.py](https://codecov.io/gh/pandas-dev/pandas/pull/17361/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ3JvdXBieS5weQ==) | `92.14% <100%> (ø)` | :arrow_up: |
| [pandas/core/generic.py](https://codecov.io/gh/pandas-dev/pandas/pull/17361/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ2VuZXJpYy5weQ==) | `95.95% <100%> (ø)` | :arrow_up: |
| [pandas/core/reshape/merge.py](https://codecov.io/gh/pandas-dev/pandas/pull/17361/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvcmVzaGFwZS9tZXJnZS5weQ==) | `94.21% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17361?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/17361?src=pr&el=footer). Last update [c19bdc9...71748b6](https://codecov.io/gh/pandas-dev/pandas/pull/17361?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

@jmmease this looks like an older version of #17484 
@jreback This PR was for the sort_values col&index change. It had some shared utility code with #17484  (the merge col&index change) so i was holding off on updating it until that one was merged.  

Do you want to keep this PR closed until #17484 is merged and I make the updates?
np can rebase and evaluate after #17484
Ok, I just pushed a bunch of updates:
- Converted to use the new `_get_label_or_level_values` utility method introduced in #17484
- Moved tests to a new file, updated to use fixtures/parametrize, and added `axis=1` test cases
- I reviewed the `sort_values` documentation in the docstrings and in `basics.rst` and made small language updates throughout.  I hope these changes make things a bit clearer and more consistent.
- I added a full whatsnew section for 0.22.0

@jreback @jorisvandenbossche @gfyoung @TomAugspurger
Just following up on this. 

@gfyoung if you have time to look this over at some point, I'd appreciate your feedback on these documentation/docstring updates.

@jreback does this approach look alright to you?

Thanks all
@jmmease lgtm. @TomAugspurger @jorisvandenbossche if you'd have a look.
Thanks for the thorough comments @jorisvandenbossche and @TomAugspurger 

I just pushed an update that I believe address all of them.  Let me know if I missed anything or if you see any other updates you'd like before this is merged.
@TomAugspurger @jorisvandenbossche Did these latest updates address your comments? Are there any other changes you'd like to see before this is merged? Thanks!

cc @jreback
Friendly ping
@TomAugspurger @jorisvandenbossche @jreback
@jreback @jorisvandenbossche @TomAugspurger  I noticed the milestone tag for this was moved to 0.23.0.  I just moved the whatsnew to this version. Are we in a freeze for merging things into 0.23.0 until 0.22.0 is released?
@jmmease 0.22 is a special release coming out today. so all previous 0.22 is now 0.23.
@jmmease just a couple of minor comments. note that windows CI is currently failing. just wait to repush.
Thanks @jreback . If I'm not mistaken, It looks like the comments you just made ("blank line", and "issue number") are against an older version of the PR. The new tests were parametrized and moved to `test_sort_values_level_as_str.py`.
@jreback The AppVeyor build is passing now, but I'm getting a "The job exceeded the maximum time limit for jobs, and has been terminated." error for most of the Travis builds.
yeah travis just started failing
not sure why
rebase and push again, fixed some hanging by Travis CI
Done. Thanks @jreback . Happy New Year BTW!
happy new year. will have a final look, but this lgtm. @TomAugspurger 
Thanks for taking a look @TomAugspurger 
Anything else @jreback ?
thanks @jmmease really nice patch! keep em coming!
Awesome, thanks for all your time on this @jreback @TomAugspurger, @jorisvandenbossche, and @gfyoung !