<h4 dir="auto">Code Sample</h4>
<p dir="auto">Create an Enum as described in the <a href="https://docs.python.org/3/library/enum.html" rel="nofollow">Python docs</a>, then create a dataframe and try to set multiindex:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from enum import Enum
import pandas as pd

class Method(Enum):
    LINEAR = 1
    CONSTANT= 2
    
df = pd.DataFrame(data={&quot;a&quot;:[Method.LINEAR, Method.CONSTANT, 
                             Method.LINEAR, Method.CONSTANT], 
                        &quot;b&quot;:[1,2,2,3],
                        &quot;c&quot;:[0,1,2,3]})
    
df.set_index([&quot;a&quot;, &quot;b&quot;])"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">enum</span> <span class="pl-k">import</span> <span class="pl-v">Enum</span>
<span class="pl-k">import</span> <span class="pl-s1">pandas</span> <span class="pl-k">as</span> <span class="pl-s1">pd</span>

<span class="pl-k">class</span> <span class="pl-v">Method</span>(<span class="pl-v">Enum</span>):
    <span class="pl-v">LINEAR</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span>
    <span class="pl-v">CONSTANT</span><span class="pl-c1">=</span> <span class="pl-c1">2</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-s1">data</span><span class="pl-c1">=</span>{<span class="pl-s">"a"</span>:[<span class="pl-v">Method</span>.<span class="pl-v">LINEAR</span>, <span class="pl-v">Method</span>.<span class="pl-v">CONSTANT</span>, 
                             <span class="pl-v">Method</span>.<span class="pl-v">LINEAR</span>, <span class="pl-v">Method</span>.<span class="pl-v">CONSTANT</span>], 
                        <span class="pl-s">"b"</span>:[<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>],
                        <span class="pl-s">"c"</span>:[<span class="pl-c1">0</span>,<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>]})
    
<span class="pl-s1">df</span>.<span class="pl-en">set_index</span>([<span class="pl-s">"a"</span>, <span class="pl-s">"b"</span>])</pre></div>
<p dir="auto">Error:</p>
<blockquote>
<p dir="auto">File "C:\A_PROGRAMS\anaconda3\lib\site-packages\pandas\core\arrays\categorical.py", line 2515, in _factorize_from_iterable<br>
cat = Categorical(values, ordered=True)<br>
File "C:\A_PROGRAMS\anaconda3\lib\site-packages\pandas\core\arrays\categorical.py", line 351, in <strong>init</strong><br>
raise TypeError("'values' is not ordered, please "</p>
</blockquote>
<h4 dir="auto">Problem description</h4>
<p dir="auto">Enum is a data type of the official Python 3 STL and should be supported by pandas. set_index works fine with enums when using them alone, e.g. <code class="notranslate">df.set_index(["a"]) </code> works.</p>
<p dir="auto">I assume that the "ordered=True" might be the problem in categorical.py?</p>
<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.5.final.0<br>
python-bits: 64<br>
OS: Windows<br>
OS-release: 7<br>
machine: AMD64<br>
processor: Intel64 Family 6 Model 94 Stepping 3, GenuineIntel<br>
byteorder: little<br>
LC_ALL: None<br>
LANG: en<br>
LOCALE: None.None</p>
<p dir="auto">pandas: 0.23.0<br>
pytest: 3.5.1<br>
pip: 10.0.1<br>
setuptools: 39.1.0<br>
Cython: 0.28.2<br>
numpy: 1.14.3<br>
scipy: 1.1.0<br>
pyarrow: 0.9.0<br>
xarray: None<br>
IPython: 6.4.0<br>
sphinx: 1.7.4<br>
patsy: 0.5.0<br>
dateutil: 2.7.3<br>
pytz: 2018.4<br>
blosc: None<br>
bottleneck: 1.2.1<br>
tables: 3.4.3<br>
numexpr: 2.6.5<br>
feather: 0.4.0<br>
matplotlib: 2.2.2<br>
openpyxl: 2.5.3<br>
xlrd: 1.1.0<br>
xlwt: 1.3.0<br>
xlsxwriter: 1.0.4<br>
lxml: 4.2.1<br>
bs4: 4.6.0<br>
html5lib: 1.0.1<br>
sqlalchemy: 1.2.7<br>
pymysql: None<br>
psycopg2: None<br>
jinja2: 2.10<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="import pandas as pd
from enum import Enum

MyEnum = Enum(&quot;MyEnum&quot;, &quot;A B&quot;)

df = pd.DataFrame(columns=pd.MultiIndex.from_product(iterables=[MyEnum, [1, 2]]))  # TypeError: 'values' is not ordered, please explicitly specify the categories order by passing in a categories argument.

df = pd.DataFrame(columns=pd.MultiIndex.from_product(iterables=[pd.Series(MyEnum, dtype=&quot;category&quot;), [1, 2]]))  # this workaround successfully executes, but...
df.append({(MyEnum.A, 1): &quot;abc&quot;, (MyEnum.B, 2): &quot;xyz&quot;}, ignore_index=True)  # ... this &quot;append&quot; statement then raises the same error.

df.loc[0, [(MyEnum.A, 1), (MyEnum.B, 2)]] = 'abc', 'xyz'  # this works, but is less desirable (can't pass a dict, need to come up with a row indexer, etc.)
"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">pandas</span> <span class="pl-k">as</span> <span class="pl-s1">pd</span>
<span class="pl-k">from</span> <span class="pl-s1">enum</span> <span class="pl-k">import</span> <span class="pl-v">Enum</span>

<span class="pl-v">MyEnum</span> <span class="pl-c1">=</span> <span class="pl-v">Enum</span>(<span class="pl-s">"MyEnum"</span>, <span class="pl-s">"A B"</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-s1">columns</span><span class="pl-c1">=</span><span class="pl-s1">pd</span>.<span class="pl-v">MultiIndex</span>.<span class="pl-en">from_product</span>(<span class="pl-s1">iterables</span><span class="pl-c1">=</span>[<span class="pl-v">MyEnum</span>, [<span class="pl-c1">1</span>, <span class="pl-c1">2</span>]]))  <span class="pl-c"># TypeError: 'values' is not ordered, please explicitly specify the categories order by passing in a categories argument.</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-s1">columns</span><span class="pl-c1">=</span><span class="pl-s1">pd</span>.<span class="pl-v">MultiIndex</span>.<span class="pl-en">from_product</span>(<span class="pl-s1">iterables</span><span class="pl-c1">=</span>[<span class="pl-s1">pd</span>.<span class="pl-v">Series</span>(<span class="pl-v">MyEnum</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s">"category"</span>), [<span class="pl-c1">1</span>, <span class="pl-c1">2</span>]]))  <span class="pl-c"># this workaround successfully executes, but...</span>
<span class="pl-s1">df</span>.<span class="pl-en">append</span>({(<span class="pl-v">MyEnum</span>.<span class="pl-v">A</span>, <span class="pl-c1">1</span>): <span class="pl-s">"abc"</span>, (<span class="pl-v">MyEnum</span>.<span class="pl-v">B</span>, <span class="pl-c1">2</span>): <span class="pl-s">"xyz"</span>}, <span class="pl-s1">ignore_index</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)  <span class="pl-c"># ... this "append" statement then raises the same error.</span>

<span class="pl-s1">df</span>.<span class="pl-s1">loc</span>[<span class="pl-c1">0</span>, [(<span class="pl-v">MyEnum</span>.<span class="pl-v">A</span>, <span class="pl-c1">1</span>), (<span class="pl-v">MyEnum</span>.<span class="pl-v">B</span>, <span class="pl-c1">2</span>)]] <span class="pl-c1">=</span> <span class="pl-s">'abc'</span>, <span class="pl-s">'xyz'</span>  <span class="pl-c"># this works, but is less desirable (can't pass a dict, need to come up with a row indexer, etc.)</span></pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">Though Enums can easily be used as column indexers, strange errors appear to arise when they are used (as one of the factors) in a MultiIndex.</p>
<p dir="auto">The multiindex (and dataframe) can be created successfully if an (ordered) categorical Series is passed to the constructor. Yet in this case, appending rows in the usual way fails. One can create new rows using <code class="notranslate">.loc</code>, and yet this is not as nice.</p>
<p dir="auto">This whole situation can be avoided by using strings instead of an Enum. Alternatively, one can use an IntEnum---and yet this essentially uses the underlying integers, instead of the names, as the column indexers.</p>
<p dir="auto">As the use of enums as columns is perfectly supported in the case of a simple index, it seems a shortcoming that they can't be used in a MultiIndex.</p>
<h4 dir="auto">Expected Output</h4>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; df = pd.DataFrame(columns=pd.MultiIndex.from_product(iterables=[MyEnum, [1, 2]]))
&gt;&gt;&gt; df
Empty DataFrame
Columns: [(MyEnum.A, 1), (MyEnum.A, 2), (MyEnum.B, 1), (MyEnum.B, 2)]
Index: []
&gt;&gt;&gt; df.append({(MyEnum.A, 1): &quot;abc&quot;, (MyEnum.B, 2): &quot;xyz&quot;}, ignore_index=True)
  MyEnum.A      MyEnum.B     
         1    2        1    2
0      abc  NaN      NaN  xyz"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</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-s1">columns</span><span class="pl-c1">=</span><span class="pl-s1">pd</span>.<span class="pl-v">MultiIndex</span>.<span class="pl-en">from_product</span>(<span class="pl-s1">iterables</span><span class="pl-c1">=</span>[<span class="pl-v">MyEnum</span>, [<span class="pl-c1">1</span>, <span class="pl-c1">2</span>]]))
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">df</span>
<span class="pl-v">Empty</span> <span class="pl-v">DataFrame</span>
<span class="pl-v">Columns</span>: [(<span class="pl-v">MyEnum</span>.<span class="pl-v">A</span>, <span class="pl-c1">1</span>), (<span class="pl-v">MyEnum</span>.<span class="pl-v">A</span>, <span class="pl-c1">2</span>), (<span class="pl-v">MyEnum</span>.<span class="pl-v">B</span>, <span class="pl-c1">1</span>), (<span class="pl-v">MyEnum</span>.<span class="pl-v">B</span>, <span class="pl-c1">2</span>)]
<span class="pl-v">Index</span>: []
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">df</span>.<span class="pl-en">append</span>({(<span class="pl-v">MyEnum</span>.<span class="pl-v">A</span>, <span class="pl-c1">1</span>): <span class="pl-s">"abc"</span>, (<span class="pl-v">MyEnum</span>.<span class="pl-v">B</span>, <span class="pl-c1">2</span>): <span class="pl-s">"xyz"</span>}, <span class="pl-s1">ignore_index</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
  <span class="pl-v">MyEnum</span>.<span class="pl-v">A</span>      <span class="pl-v">MyEnum</span>.<span class="pl-v">B</span>     
         <span class="pl-c1">1</span>    <span class="pl-c1">2</span>        <span class="pl-c1">1</span>    <span class="pl-c1">2</span>
<span class="pl-c1">0</span>      <span class="pl-s1">abc</span>  <span class="pl-v">NaN</span>      <span class="pl-v">NaN</span>  <span class="pl-s1">xyz</span></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: Darwin<br>
OS-release: 17.5.0<br>
machine: x86_64<br>
processor: i386<br>
byteorder: little<br>
LC_ALL: None<br>
LANG: en_US.UTF-8<br>
LOCALE: en_US.UTF-8</p>
<p dir="auto">pandas: 0.23.0<br>
pytest: None<br>
pip: 10.0.1<br>
setuptools: 39.0.1<br>
Cython: None<br>
numpy: 1.13.3<br>
scipy: None<br>
pyarrow: None<br>
xarray: None<br>
IPython: None<br>
sphinx: None<br>
patsy: None<br>
dateutil: 2.6.1<br>
pytz: 2017.3<br>
blosc: None<br>
bottleneck: None<br>
tables: None<br>
numexpr: None<br>
feather: None<br>
matplotlib: None<br>
openpyxl: None<br>
xlrd: None<br>
xlwt: None<br>
xlsxwriter: None<br>
lxml: None<br>
bs4: None<br>
html5lib: None<br>
sqlalchemy: None<br>
pymysql: None<br>
psycopg2: None<br>
jinja2: None<br>
s3fs: None<br>
fastparquet: None<br>
pandas_gbq: None<br>
pandas_datareader: None</p>
</details>