DEPR: deprecate .ix in favor of .loc/.iloc
State: closed

closes #14218 
closes #15116 

This shows a pretty big deprecation message, though its instructive.
```
In [1]: df = pd.DataFrame({'A': [1, 2, 3],
   ...:                        'B': [4, 5, 6]},
   ...:                       index=list('abc'))
   ...: df
   ...: 
Out[1]: 
   A  B
a  1  4
b  2  5
c  3  6

In [2]: df.ix[[0, 2], 'A']
/Users/jreback/miniconda3/envs/pandas/bin/ipython:1: FutureWarning: 
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing

You an do multi-axes indexing like the following
>>> df = pd.DataFrame({'A': [1, 2, 3],
                       'B': [4, 5, 6]},
                      index=list('abc'))
>>> df
   A  B
a  1  4
b  2  5
c  3  6

From prior versions
>>> df.ix[[0, 2], 'A']
a    1
c    3
Name: A, dtype: int64

Using .loc
>>> df.loc[df.index[[0, 2]], 'A']
a    1
c    3
Name: A, dtype: int64

Using .iloc
>>> df.iloc[[0, 2]], df.columns.get_loc('A')]
a    1
c    3
Name: A, dtype: int64
```

Labels:
name: Indexing
description: Related to indexing on series/frames, not to indexes themselves
name: Deprecate
description: Functionality to remove in pandas

Comments:
This is the big kahuna! wasn't that difficult, mostly did a search-and-replace of ``.ix`` -> ``.loc`` then fixed the errors.
@jorisvandenbossche @TomAugspurger @shoyer @cpcloud @wesm @sinhrks @chris-b1 
very nice!
## [Current coverage](https://codecov.io/gh/pandas-dev/pandas/pull/15113?src=pr) is 85.53% (diff: 97.36%)
> Merging [#15113](https://codecov.io/gh/pandas-dev/pandas/pull/15113?src=pr) into [master](https://codecov.io/gh/pandas-dev/pandas/branch/master?src=pr) will decrease coverage by **0.01%**

```diff
@@             master     #15113   diff @@
==========================================
  Files           145        145          
  Lines         51352      51361     +9   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
  Hits          43932      43932          
- Misses         7420       7429     +9   
  Partials          0          0          
```

> Powered by [Codecov](https://codecov.io?src=pr). Last update [362e78d...0bf5cb5](https://codecov.io/gh/pandas-dev/pandas/compare/362e78d944cc72d9da95c7feb0e7d385a63beeae...0bf5cb5ab4dc75727e6aa323599c064c3446e0ef?src=pr)
Or maybe `df.iloc[[0, 2]].A`
Awesome!

That's a long message. Is it worth having a shorter message including a link to the docs? 
i changed the message to have a link
could skip the example if people think it's too long
This is great!

Deprecation warnings tend to turn up downstream in application code, where they are often read by users for whom they are not relevant. This is a necessary evil, but to reduce their burden it's best to keep them short. I would stick to a few lines with a link, e.g.,
```
.ix is deprecated. Please use .loc for label based indexing or .iloc for
positional indexing. For more details, see:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate_ix
```
I would be in favor for that reason to go with a more 'softer' deprecation, and in a first place use DeprecationWarnings (these should still be visible by default in interactive usage in ipython), and only in a second phase (one or few releases later) a more visible FutureWarning. 
`.ix` is used massively, and users will otherwise be flooded with warnings when using library code depending on pandas (which I personally find very annoying). 
> No matter that this is the intended behaviour of get_loc/get_indexer, it makes it again more complex for the user.

That's just an alternative, I think it is *much more* clear to use direct indexing and use ``.loc``

thus

``df.loc[df.index[[0, 2]], 'A']`` or whatever is pretty much a direct translation. I will relegate ``.get_loc/.get_indexer`` I think to a smaller section (as that really isn't the recommended way I think).
ok I updated all of the docs that I could as well.
@jorisvandenbossche do you feel strongly about this being a ``DeprecationWarning`` rather than a ``FutureWarning``? I don't think we do that for anything else IIRC, though this is more visibile than anything else we have done.
> @jorisvandenbossche do you feel strongly about this being a DeprecationWarning rather than a FutureWarning? I don't think we do that for anything else IIRC, though this is more visibile than anything else we have done.

I am personally in favor of using a DeprecationWarning, yes. But would love to hear some other opinions. 

The reason that I am in favor is because, if we use FutureWarning, many users will see them (from external libraries they use), don't know where they come from or what they can do about it. Of course you specifically silence them, but that is not very friendly to novice users. 
And remember that, even when using DeprecationWarning, those are visible in an interactive IPython session (if the stacklevel is set correctly, but that is the case). So you still get warned for direct interactive usage.

Using DeprecationWarning now gives package authors some time to clean-up first (of course, assuming they turn on deprecation warnings in their tests. But eg seaborn and statsmodels both have uses of `.ix`). And after some time, we can still turn the DeprecationWarning into a more visible FutureWarning.

We do this currently like this for the deprecations in `core.common`, but as I was the one in favor there as well and changed this, that is not really a reference :-)
ok, I will change this to ``DeprecationWarning``; also will create an issue to change this for the next version of pandas.
Also +1 for `DeprecationWaring` then `FutureWarning` in the next release.

I started to work on removing `.ix` from statsmodels. 300ish uses from a quick grep IIRC.