Accept CategoricalDtype in read_csv
State: closed

```python
import pandas as pd
from io import StringIO
from pandas.api.types import CategoricalDtype

data = 'col1,col2,col3\na,b,1\na,b,2\nc,d,3'

dtype = CategoricalDtype(['d', 'c', 'b', 'a'], ordered=True)
pd.read_csv(StringIO(data), dtype={'col1': dtype}).dtypes
```


This is for after https://github.com/pandas-dev/pandas/pull/16015

cc @chris-b1 

Labels:
name: IO CSV
description: read_csv, to_csv
name: Categorical
description: Categorical Data Type

Comments:
I squashed everything from #16015 down to a single commit, so the changes here are just https://github.com/pandas-dev/pandas/pull/17643/commits/ccbaa04f1745f41cced0f48c2047094e293a864
This should be ready to go. My earlier implementation was buggy and only worked when the data were already sorted.

Casting is now implemented by

1. checking if `dtype.categories` is {numeric,datetime,timedelta} type
2. calling the appropriate `to_*` function to cast the values / inferred categories

One question I had is how to control options passed to that function. I've simply hardcoded `errors='ignore'`. I'm leery about trying to be clever here.
> What (should) happens when there are values in the csv file column that are not specified in the categories?

Ah I forgot about this case. Yes, I think we will insert NaNs then. In my mind this should behave like a `.set_categories(dtype.categories)` after the fact. I'll add tests and docs for this tomorrow.
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@7e87385`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `100%`.

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

```diff
@@            Coverage Diff            @@
##             master   #17643   +/-   ##
=========================================
  Coverage          ?   91.24%           
=========================================
  Files             ?      163           
  Lines             ?    49819           
  Branches          ?        0           
=========================================
  Hits              ?    45456           
  Misses            ?     4363           
  Partials          ?        0
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.04% <100%> (?)` | |
| #single | `40.31% <14.28%> (?)` | |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/io/parsers.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2lvL3BhcnNlcnMucHk=) | `95.51% <100%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/17643?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/17643?src=pr&el=footer). Last update [7e87385...6f175a7](https://codecov.io/gh/pandas-dev/pandas/pull/17643?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/17643?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@7e87385`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `100%`.

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

```diff
@@            Coverage Diff            @@
##             master   #17643   +/-   ##
=========================================
  Coverage          ?   91.24%           
=========================================
  Files             ?      163           
  Lines             ?    49819           
  Branches          ?        0           
=========================================
  Hits              ?    45456           
  Misses            ?     4363           
  Partials          ?        0
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.04% <100%> (?)` | |
| #single | `40.31% <14.28%> (?)` | |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/io/parsers.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2lvL3BhcnNlcnMucHk=) | `95.51% <100%> (ø)` | |

------

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

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

```diff
@@            Coverage Diff             @@
##           master   #17643      +/-   ##
==========================================
- Coverage   91.27%   91.23%   -0.04%     
==========================================
  Files         163      163              
  Lines       49765    49848      +83     
==========================================
+ Hits        45421    45480      +59     
- Misses       4344     4368      +24
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.03% <100%> (-0.02%)` | :arrow_down: |
| #single | `40.32% <7.4%> (-0.09%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/categorical.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvY2F0ZWdvcmljYWwucHk=) | `95.73% <100%> (+0.02%)` | :arrow_up: |
| [pandas/io/parsers.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2lvL3BhcnNlcnMucHk=) | `95.49% <100%> (ø)` | :arrow_up: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :arrow_down: |
| [pandas/core/tools/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvdG9vbHMvZGF0ZXRpbWVzLnB5) | `82.97% <0%> (-0.83%)` | :arrow_down: |
| [pandas/core/common.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvY29tbW9uLnB5) | `91.42% <0%> (-0.56%)` | :arrow_down: |
| [pandas/core/indexes/multi.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9tdWx0aS5weQ==) | `96.39% <0%> (-0.51%)` | :arrow_down: |
| [pandas/core/config.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvY29uZmlnLnB5) | `87.7% <0%> (-0.39%)` | :arrow_down: |
| [pandas/core/indexes/category.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9jYXRlZ29yeS5weQ==) | `97.46% <0%> (-0.29%)` | :arrow_down: |
| [pandas/core/groupby.py](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ3JvdXBieS5weQ==) | `92.04% <0%> (-0.2%)` | :arrow_down: |
| ... and [15 more](https://codecov.io/gh/pandas-dev/pandas/pull/17643?src=pr&el=tree-more) | |

------

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

Hmm, seems like the compiler error is back on circle CI. Looking into it.
All green. Merging.

I opened up https://github.com/pandas-dev/pandas/issues/17743 for optimizing `_categorical_convert` in the C parser. I won't have time to get to it for the release though.
Thanks!
thanks @TomAugspurger this is great!