<h4 dir="auto">Code Sample, a copy-pastable example if possible</h4>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="a = pd.DataFrame({
    'ID': [1, 1, 2, 2],
    'GENDER': ['male', 'male', 'female', 'female'],
})

a.GENDER = a.GENDER.astype('category')

a.groupby('ID').last().GENDER
"><pre class="notranslate"><span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>({
    <span class="pl-s">'ID'</span>: [<span class="pl-c1">1</span>, <span class="pl-c1">1</span>, <span class="pl-c1">2</span>, <span class="pl-c1">2</span>],
    <span class="pl-s">'GENDER'</span>: [<span class="pl-s">'male'</span>, <span class="pl-s">'male'</span>, <span class="pl-s">'female'</span>, <span class="pl-s">'female'</span>],
})

<span class="pl-s1">a</span>.<span class="pl-v">GENDER</span> <span class="pl-c1">=</span> <span class="pl-s1">a</span>.<span class="pl-v">GENDER</span>.<span class="pl-en">astype</span>(<span class="pl-s">'category'</span>)

<span class="pl-s1">a</span>.<span class="pl-en">groupby</span>(<span class="pl-s">'ID'</span>).<span class="pl-en">last</span>().<span class="pl-v">GENDER</span></pre></div>
<p dir="auto">Output</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ID
1      male
2    female
Name: GENDER, dtype: object"><pre class="notranslate"><code class="notranslate">ID
1      male
2    female
Name: GENDER, dtype: object
</code></pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">I would expect that categoricals are preserved by such transformations. At best, the transformation returns an updated categorical if some categories are missing in the process.</p>
<h4 dir="auto">Expected output</h4>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ID
1      male
2    female
Name: GENDER, dtype: category
Categories (2, object): [female, male]"><pre class="notranslate"><code class="notranslate">ID
1      male
2    female
Name: GENDER, dtype: category
Categories (2, object): [female, male]
</code></pre></div>
<h4 dir="auto">Output of <code class="notranslate">pd.show_versions()</code></h4>
<details>
<h2 dir="auto">INSTALLED VERSIONS</h2>
<p dir="auto">commit: None<br>
python: 3.6.3.final.0<br>
python-bits: 64<br>
OS: Windows<br>
OS-release: 10<br>
machine: AMD64<br>
processor: Intel64 Family 6 Model 69 Stepping 1, GenuineIntel<br>
byteorder: little<br>
LC_ALL: None<br>
LANG: None<br>
LOCALE: None.None</p>
<p dir="auto">pandas: 0.21.0<br>
pytest: 3.2.1<br>
pip: 9.0.1<br>
setuptools: 36.5.0.post20170921<br>
Cython: 0.26.1<br>
numpy: 1.13.3<br>
scipy: 0.19.1<br>
pyarrow: None<br>
xarray: None<br>
IPython: 6.1.0<br>
sphinx: 1.6.3<br>
patsy: 0.4.1<br>
dateutil: 2.6.1<br>
pytz: 2017.3<br>
blosc: None<br>
bottleneck: 1.2.1<br>
tables: 3.4.2<br>
numexpr: 2.6.2<br>
feather: None<br>
matplotlib: 2.1.0<br>
openpyxl: 2.4.8<br>
xlrd: 1.1.0<br>
xlwt: 1.3.0<br>
xlsxwriter: 1.0.2<br>
lxml: 4.1.0<br>
bs4: 4.6.0<br>
html5lib: 0.999999999<br>
sqlalchemy: 1.1.13<br>
pymysql: None<br>
psycopg2: None<br>
jinja2: 2.9.6<br>
s3fs: None<br>
fastparquet: None<br>
pandas_gbq: None<br>
pandas_datareader: None</p>
</details>
<h4 dir="auto">Code Sample, a copy-pastable example if possible</h4>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# Your code here

    In [1]: df=pd.DataFrame(dict(payload=[-1,-2,-1,-2], col=pd.Categorical([&quot;foo&quot;, &quot;bar&quot;, &quot;bar&quot;, &quot;qux&quot;], ordered=True)));df
    Out[1]: 
       col  payload
    0  foo       -1
    1  bar       -2
    2  bar       -1
    3  qux       -2

    In [2]: df.groupby(&quot;payload&quot;).first().col.dtype
    Out[2]: dtype('O')
"><pre class="notranslate"><span class="pl-c"># Your code here</span>

    <span class="pl-v">In</span> [<span class="pl-c1">1</span>]: <span class="pl-s1">df</span><span class="pl-c1">=</span><span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-en">dict</span>(<span class="pl-s1">payload</span><span class="pl-c1">=</span>[<span class="pl-c1">-</span><span class="pl-c1">1</span>,<span class="pl-c1">-</span><span class="pl-c1">2</span>,<span class="pl-c1">-</span><span class="pl-c1">1</span>,<span class="pl-c1">-</span><span class="pl-c1">2</span>], <span class="pl-s1">col</span><span class="pl-c1">=</span><span class="pl-s1">pd</span>.<span class="pl-v">Categorical</span>([<span class="pl-s">"foo"</span>, <span class="pl-s">"bar"</span>, <span class="pl-s">"bar"</span>, <span class="pl-s">"qux"</span>], <span class="pl-s1">ordered</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)));<span class="pl-s1">df</span>
    <span class="pl-v">Out</span>[<span class="pl-c1">1</span>]: 
       <span class="pl-s1">col</span>  <span class="pl-s1">payload</span>
    <span class="pl-c1">0</span>  <span class="pl-s1">foo</span>       <span class="pl-c1">-</span><span class="pl-c1">1</span>
    <span class="pl-c1">1</span>  <span class="pl-s1">bar</span>       <span class="pl-c1">-</span><span class="pl-c1">2</span>
    <span class="pl-c1">2</span>  <span class="pl-s1">bar</span>       <span class="pl-c1">-</span><span class="pl-c1">1</span>
    <span class="pl-c1">3</span>  <span class="pl-s1">qux</span>       <span class="pl-c1">-</span><span class="pl-c1">2</span>

    <span class="pl-v">In</span> [<span class="pl-c1">2</span>]: <span class="pl-s1">df</span>.<span class="pl-en">groupby</span>(<span class="pl-s">"payload"</span>).<span class="pl-en">first</span>().<span class="pl-s1">col</span>.<span class="pl-s1">dtype</span>
    <span class="pl-v">Out</span>[<span class="pl-c1">2</span>]: <span class="pl-en">dtype</span>(<span class="pl-s">'O'</span>)</pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">Grouping shouldn't coerce a categorical into object. Categorical dtypes should be preserved as long as possible for efficiency and correctness.</p>
<h4 dir="auto">Expected Output</h4>
<p dir="auto">The result dtype should be CategoricalDtype(categories=['bar', 'foo', 'qux'], ordered=True), just like it is here:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="    In [6]: df.groupby(&quot;payload&quot;).head().col.dtype
    Out[6]: CategoricalDtype(categories=['bar', 'foo', 'qux'], ordered=True

#### Output of ``pd.show_versions()``

&lt;details&gt;
    INSTALLED VERSIONS
    ------------------
    commit: None
    python: 3.4.3.final.0
    python-bits: 64
    OS: Linux
    OS-release: 4.4.0-98-generic
    machine: x86_64
    processor: x86_64
    byteorder: little
    LC_ALL: None
    LANG: en_US.UTF-8
    LOCALE: en_US.UTF-8

    pandas: 0.21.0
    pytest: 3.2.5
    pip: 9.0.1
    setuptools: 36.5.0
    Cython: 0.20.1post0
    numpy: 1.13.3
    scipy: 0.13.3
    pyarrow: None
    xarray: 0.9.6
    IPython: 6.2.0
    sphinx: None
    patsy: None
    dateutil: 2.6.1
    pytz: 2017.3
    blosc: None
    bottleneck: None
    tables: 3.1.1
    numexpr: 2.6.4
    feather: None
    matplotlib: 1.3.1
    openpyxl: None
    xlrd: None
    xlwt: None
    xlsxwriter: None
    lxml: None
    bs4: 4.2.1
    html5lib: 0.999
    sqlalchemy: 0.8.4
    pymysql: None
    psycopg2: None
    jinja2: 2.7.2
    s3fs: 0.1.2
    fastparquet: None
    pandas_gbq: None
    pandas_datareader: None
[paste the output of ``pd.show_versions()`` here below this line]

&lt;/details&gt;"><pre class="notranslate">    <span class="pl-v">In</span> [<span class="pl-c1">6</span>]: <span class="pl-s1">df</span>.<span class="pl-en">groupby</span>(<span class="pl-s">"payload"</span>).<span class="pl-en">head</span>().<span class="pl-s1">col</span>.<span class="pl-s1">dtype</span>
    <span class="pl-v">Out</span>[<span class="pl-c1">6</span>]: <span class="pl-v">CategoricalDtype</span>(<span class="pl-s1">categories</span><span class="pl-c1">=</span>[<span class="pl-s">'bar'</span>, <span class="pl-s">'foo'</span>, <span class="pl-s">'qux'</span>], <span class="pl-s1">ordered</span><span class="pl-c1">=</span><span class="pl-c1">True</span>

<span class="pl-c">#### Output of ``pd.show_versions()``</span>

<span class="pl-c1">&lt;</span><span class="pl-s1">details</span><span class="pl-c1">&gt;</span>
    <span class="pl-v">INSTALLED</span> <span class="pl-v">VERSIONS</span>
    <span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span>
    <span class="pl-s1">commit</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">python</span>: <span class="pl-c1">3.4</span><span class="pl-c1">.3</span>.<span class="pl-s1">final</span><span class="pl-c1">.0</span>
    <span class="pl-s1">python</span><span class="pl-c1">-</span><span class="pl-s1">bits</span>: <span class="pl-c1">64</span>
    <span class="pl-v">OS</span>: <span class="pl-v">Linux</span>
    <span class="pl-v">OS</span><span class="pl-c1">-</span><span class="pl-s1">release</span>: <span class="pl-c1">4.4</span><span class="pl-c1">.0</span><span class="pl-c1">-</span><span class="pl-c1">98</span><span class="pl-c1">-</span><span class="pl-s1">generic</span>
    <span class="pl-s1">machine</span>: <span class="pl-s1">x86_64</span>
    <span class="pl-s1">processor</span>: <span class="pl-s1">x86_64</span>
    <span class="pl-s1">byteorder</span>: <span class="pl-s1">little</span>
    <span class="pl-v">LC_ALL</span>: <span class="pl-c1">None</span>
    <span class="pl-v">LANG</span>: <span class="pl-s1">en_US</span>.<span class="pl-v">UTF</span><span class="pl-c1">-</span><span class="pl-c1">8</span>
    <span class="pl-v">LOCALE</span>: <span class="pl-s1">en_US</span>.<span class="pl-v">UTF</span><span class="pl-c1">-</span><span class="pl-c1">8</span>

    <span class="pl-s1">pandas</span>: <span class="pl-c1">0.21</span>.<span class="pl-c1">0</span>
    <span class="pl-s1">pytest</span>: <span class="pl-c1">3.2</span>.<span class="pl-c1">5</span>
    <span class="pl-s1">pip</span>: <span class="pl-c1">9.0</span>.<span class="pl-c1">1</span>
    <span class="pl-s1">setuptools</span>: <span class="pl-c1">36.5</span>.<span class="pl-c1">0</span>
    <span class="pl-v">Cython</span>: <span class="pl-c1">0.20</span>.<span class="pl-c1">1</span><span class="pl-s1">post0</span>
    <span class="pl-s1">numpy</span>: <span class="pl-c1">1.13</span>.<span class="pl-c1">3</span>
    <span class="pl-s1">scipy</span>: <span class="pl-c1">0.13</span>.<span class="pl-c1">3</span>
    <span class="pl-s1">pyarrow</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">xarray</span>: <span class="pl-c1">0.9</span>.<span class="pl-c1">6</span>
    <span class="pl-v">IPython</span>: <span class="pl-c1">6.2</span>.<span class="pl-c1">0</span>
    <span class="pl-s1">sphinx</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">patsy</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">dateutil</span>: <span class="pl-c1">2.6</span>.<span class="pl-c1">1</span>
    <span class="pl-s1">pytz</span>: <span class="pl-c1">2017.3</span>
    <span class="pl-s1">blosc</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">bottleneck</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">tables</span>: <span class="pl-c1">3.1</span>.<span class="pl-c1">1</span>
    <span class="pl-s1">numexpr</span>: <span class="pl-c1">2.6</span>.<span class="pl-c1">4</span>
    <span class="pl-s1">feather</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">matplotlib</span>: <span class="pl-c1">1.3</span>.<span class="pl-c1">1</span>
    <span class="pl-s1">openpyxl</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">xlrd</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">xlwt</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">xlsxwriter</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">lxml</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">bs4</span>: <span class="pl-c1">4.2</span>.<span class="pl-c1">1</span>
    <span class="pl-s1">html5lib</span>: <span class="pl-c1">0.999</span>
    <span class="pl-s1">sqlalchemy</span>: <span class="pl-c1">0.8</span>.<span class="pl-c1">4</span>
    <span class="pl-s1">pymysql</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">psycopg2</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">jinja2</span>: <span class="pl-c1">2.7</span>.<span class="pl-c1">2</span>
    <span class="pl-s1">s3fs</span>: <span class="pl-c1">0.1</span>.<span class="pl-c1">2</span>
    <span class="pl-s1">fastparquet</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">pandas_gbq</span>: <span class="pl-c1">None</span>
    <span class="pl-s1">pandas_datareader</span>: <span class="pl-c1">None</span>
[<span class="pl-s1">paste</span> <span class="pl-s1">the</span> <span class="pl-s1">output</span> <span class="pl-s1">of</span> <span class="pl-s">``</span><span class="pl-s1">pd</span>.<span class="pl-en">show_versions</span>()<span class="pl-s">``</span> <span class="pl-s1">here</span> <span class="pl-s1">below</span> <span class="pl-s1">this</span> <span class="pl-s1">line</span>]

<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-s1">details</span><span class="pl-c1">&gt;</span></pre></div>