allow rename to work with any Mapping, not just dict
State: closed

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html claims to work with a dict-like object, but according to https://github.com/jab/bidict/issues/18#issuecomment-147643550 it does not. This patch changes `isinstance(..., dict)` to `isinstance(..., collections.abc.Mapping)` as a first pass attempt to bring the code more in line with the documentation.


Labels:
name: Enhancement
name: Compat
description: pandas objects compatability with Numpy or Python functions

Comments:
sounds reasonable..

would need some tests

Note: In https://mail.python.org/pipermail/python-dev/2015-October/142058.html Python core developer @brettcannon advises against using `isinstance` in general. So this could be a first step while any further improvements are pending.

> would need some tests

I'm actually not even a pandas user myself. I'm the author of https://github.com/jab/bidict, and one of my users hit this but mistakenly reported the bug in bidict rather than pandas. Since no one has done that yet, I thought I'd try to get the ball rolling and even try to contribute a fix. Would love to kick this back to the pandas community for any further changes needed to get this merged if possible.

contributing docs are [here](http://pandas.pydata.org/pandas-docs/stable/contributing.html)

sooner tests and a whatsnew note are written, the sooner it will be merged.

@jab and the reason we use `isinstance` extensively its doing try/except is MUCH slower, yes its prob a tad bit more pythonic, but practicality almost always beats purity :smile: 

Just gave you all push access to https://github.com/jab/pandas so you can take it from here.

@jreback Just to be clear, try/except clauses are only slow when an exception is raised and so you should only worry about avoiding them for performance when you think the raise/not raise ratio cases go against exceptions, otherwise try/except is faster than an `if` statement in the successful case.

```
PS C:\Users\brcan> py -m timeit -c "example = {'a': 42}" "try: example['a']" "except KeyError: pass"
10000000 loops, best of 3: 0.13 usec per loop
PS C:\Users\brcan> py -m timeit -c "example = {'a': 42}" "if isinstance(example, dict):" " example['a']"
1000000 loops, best of 3: 0.209 usec per loop
PS C:\Users\brcan> py -m timeit -c "example = {'a': 42}" "if isinstance(example, list):" " example['a']"
1000000 loops, best of 3: 0.212 usec per loop
PS C:\Users\brcan> py -m timeit -c "example = {'a': 42}" "try: example.append('b')" "except AttributeError: pass"
1000000 loops, best of 3: 0.565 usec per loop
```

@brettcannon I guess I should elaborate a bit.
- `isinstance` vs `try/except` is almost always better if you don't a-prior know the distribution of included values
- yes duck-typing is great, but sometimes you really do need to know if its an `int` vs a `float`
- when you DO care about the differences, the the syntactical differences annoying (meaning you would have to do nested `try/except` vs a straight `if/elseif` with an `isinstance` in the predicate

of course all my2c

@jreback Agreed on all points but the syntax one, but that's just me :)

@jab pls update and add some tests

sorry don't have time. close if you don't care to do it yourself.

Just came across this old PR again (which wasn't merged), good to see the same issue was eventually fixed by someone else: https://github.com/pandas-dev/pandas/blob/5c0da7dd4034427745038381e8e2b77ac8c59d08/pandas/core/common.py#L478