Improve dictionary map performance on category series, fixes #23785
State: closed

- [x] closes #23785
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry

Uses the built-in categorical series mapper when mapping categorical series with dictionaries or series (i.e., as opposed to with lambada functions) instead of reindexing in order to improve performance.

## benchmarking with asv
I added some new benchmarks to test mapping performance -- performance improves substantially when mapping with dicts or series against categorical series
```
       before           after         ratio
     [181f972d]       [184feb77]
     <master~1>                 
-     1.90±0.01ms          976±8μs     0.51  series_methods.Map.time_map('dict', 'category')
-     1.33±0.01ms          418±2μs     0.31  series_methods.Map.time_map('Series', 'category')

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.
```

## benchmarking using example from #23785
upstream master
```python
import pandas as pd
print(pd.__version__)
# 0.24.2
x = pd.Series(list('abcd') * 1000).astype('category')
mapper = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
%timeit x.map(mapper)
# 904 µs ± 3.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit x.map(lambda a: mapper[a])
# 254 µs ± 997 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

this diff
```python
import pandas as pd
print(pd.__version__)
# 0.25.0.dev0+379.g184feb77e
x = pd.Series(list('abcd') * 1000).astype('category')
mapper = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
%timeit x.map(mapper)
# 622 µs ± 1.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit x.map(lambda a: mapper[a])
# 256 µs ± 4.72 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

Labels:
name: Performance
description: Memory or execution speed performance
name: Categorical
description: Categorical Data Type

Comments:
can you merge master and update
Yes I’ll make these changes tonight

On Tue, Apr 9, 2019 at 7:45 AM Jeff Reback <notifications@github.com> wrote:

> can you merge master and update
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/pandas-dev/pandas/pull/26015#issuecomment-481282523>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ASq_BQ-RFXrTzKSbYQ5ImXCsJXZbdFb0ks5vfKeKgaJpZM4cgSar>
> .
>

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

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

```diff
@@            Coverage Diff             @@
##           master   #26015      +/-   ##
==========================================
- Coverage   91.84%   91.81%   -0.03%     
==========================================
  Files         175      175              
  Lines       52517    52553      +36     
==========================================
+ Hits        48232    48254      +22     
- Misses       4285     4299      +14
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.38% <100%> (-0.02%)` | :arrow_down: |
| #single | `40.72% <50%> (-0.14%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/26015?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/base.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYmFzZS5weQ==) | `97.79% <100%> (ø)` | :arrow_up: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `75% <0%> (-12.5%)` | :arrow_down: |
| [pandas/compat/\_\_init\_\_.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvbXBhdC9fX2luaXRfXy5weQ==) | `75.83% <0%> (-2.08%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `96.79% <0%> (-0.12%)` | :arrow_down: |
| [pandas/tseries/holiday.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvaG9saWRheS5weQ==) | `93.17% <0%> (-0.04%)` | :arrow_down: |
| [pandas/plotting/\_core.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL3Bsb3R0aW5nL19jb3JlLnB5) | `83.85% <0%> (-0.02%)` | :arrow_down: |
| [pandas/tseries/frequencies.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvZnJlcXVlbmNpZXMucHk=) | `97.68% <0%> (-0.01%)` | :arrow_down: |
| [pandas/tseries/offsets.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvb2Zmc2V0cy5weQ==) | `96.69% <0%> (-0.01%)` | :arrow_down: |
| [pandas/core/generic.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ2VuZXJpYy5weQ==) | `93.54% <0%> (ø)` | :arrow_up: |
| [pandas/core/apply.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXBwbHkucHk=) | `98.61% <0%> (ø)` | :arrow_up: |
| ... and [4 more](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/26015?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/26015?src=pr&el=footer). Last update [9d66bdf...4559993](https://codecov.io/gh/pandas-dev/pandas/pull/26015?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/26015?src=pr&el=h1) Report
> Merging [#26015](https://codecov.io/gh/pandas-dev/pandas/pull/26015?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/b6324be64884afdd2829e046748b7e843e338c65?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/26015/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/26015?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #26015      +/-   ##
==========================================
- Coverage   91.98%   91.97%   -0.01%     
==========================================
  Files         175      175              
  Lines       52376    52378       +2     
==========================================
- Hits        48178    48175       -3     
- Misses       4198     4203       +5
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.53% <100%> (-0.01%)` | :arrow_down: |
| #single | `40.72% <50%> (-0.15%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/26015?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/base.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYmFzZS5weQ==) | `97.98% <100%> (-0.22%)` | :arrow_down: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `78.94% <0%> (-10.53%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/26015/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `96.9% <0%> (-0.12%)` | :arrow_down: |

------

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

can you merge master
looks good. can you merge master; ping on green.
@jreback merged master and all checks green
can you merge master; ping on green.
@jreback merged and green
thanks @rtlee9