<p dir="auto">I experience these strange behavior of <code class="notranslate">unstack()</code> when its <code class="notranslate">level</code> parameter gets a list instead of string.<br>
This changes <code class="notranslate">dtype</code> of some columns from numeric to object, which is obviously a worrying change.<br>
I am wondering if this a bug or there is something I am missing about dealing with this.<br>
I am on pandas 0.16.0, numpy 1.9.2.</p>
<p dir="auto">Here is a code to illustrate the problem:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="data = &quot;&quot;&quot;a,b,c,d
2,101,A,11
3,101,A,12
1,201,B,21
2,201,B,22
3,201,B,23
1,301,C,33
2,301,C,32&quot;&quot;&quot;
df = pd.read_csv(pd.core.common.StringIO(data))
print df.dtypes
df_str = df.set_index(['a','b']).unstack(level='a')  # Note that level has a str
print df_str.dtypes
df_list = df.set_index(['a','b']).unstack(level=['a'])  # Note that level has a list
print df_list.dtypes"><pre class="notranslate"><code class="notranslate">data = """a,b,c,d
2,101,A,11
3,101,A,12
1,201,B,21
2,201,B,22
3,201,B,23
1,301,C,33
2,301,C,32"""
df = pd.read_csv(pd.core.common.StringIO(data))
print df.dtypes
df_str = df.set_index(['a','b']).unstack(level='a')  # Note that level has a str
print df_str.dtypes
df_list = df.set_index(['a','b']).unstack(level=['a'])  # Note that level has a list
print df_list.dtypes
</code></pre></div>
<p dir="auto">Which produces:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="a     int64
b     int64
c    object
d     int64   &lt;-- Note original dtype
dtype: object

   a
c  1     object
   2     object
   3     object
d  1    float64   &lt;-- expected change of dtype due to NaN addition
   2    float64   &lt;-- expected change of dtype due to NaN addition
   3    float64   &lt;-- expected change of dtype due to NaN addition
dtype: object

   a
c  2    object
   3    object
   1    object
d  2    object   &lt;-- UNexpected change of dtype, when level got list
   3    object   &lt;-- UNexpected change of dtype, when level got list
   1    object   &lt;-- UNexpected change of dtype, when level got list
dtype: object"><pre class="notranslate"><code class="notranslate">a     int64
b     int64
c    object
d     int64   &lt;-- Note original dtype
dtype: object

   a
c  1     object
   2     object
   3     object
d  1    float64   &lt;-- expected change of dtype due to NaN addition
   2    float64   &lt;-- expected change of dtype due to NaN addition
   3    float64   &lt;-- expected change of dtype due to NaN addition
dtype: object

   a
c  2    object
   3    object
   1    object
d  2    object   &lt;-- UNexpected change of dtype, when level got list
   3    object   &lt;-- UNexpected change of dtype, when level got list
   1    object   &lt;-- UNexpected change of dtype, when level got list
dtype: object
</code></pre></div>
<p dir="auto">shouldn't the last two examples remove the innermost index level?</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="In [69]: from pandas.util.testing import makeCustomDataframe as mkdf
    ...: mkdf(4,2,r_idx_nlevels=1).set_index(&quot;C_l0_g0&quot;,append=True,drop=False)
Out[69]: 
C0              C_l0_g0 C_l0_g1
R0      C_l0_g0                
R_l0_g0 R0C0       R0C0    R0C1
R_l0_g1 R1C0       R1C0    R1C1
R_l0_g2 R2C0       R2C0    R2C1
R_l0_g3 R3C0       R3C0    R3C1

In [70]: from pandas.util.testing import makeCustomDataframe as mkdf
    ...: mkdf(4,2,r_idx_nlevels=1).set_index(&quot;C_l0_g0&quot;,append=True,drop=False).reset_index(0)
Out[70]: 
C0            R0 C_l0_g0 C_l0_g1
C_l0_g0                         
R0C0     R_l0_g0    R0C0    R0C1
R1C0     R_l0_g1    R1C0    R1C1
R2C0     R_l0_g2    R2C0    R2C1
R3C0     R_l0_g3    R3C0    R3C1"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-c1">69</span>]: <span class="pl-s1">from</span> <span class="pl-s1">pandas</span>.<span class="pl-s1">util</span>.<span class="pl-s1">testing</span> <span class="pl-s1">import</span> <span class="pl-s1">makeCustomDataframe</span> <span class="pl-k">as</span> <span class="pl-s1">mkdf</span>
    ...: <span class="pl-en">mkdf</span>(<span class="pl-c1">4</span>,<span class="pl-c1">2</span>,<span class="pl-s1">r_idx_nlevels</span><span class="pl-c1">=</span><span class="pl-c1">1</span>).<span class="pl-en">set_index</span>(<span class="pl-s">"C_l0_g0"</span>,<span class="pl-s1">append</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,<span class="pl-s1">drop</span><span class="pl-c1">=</span><span class="pl-c1">False</span>)
<span class="pl-v">Out</span>[<span class="pl-c1">69</span>]: 
<span class="pl-v">C0</span>              <span class="pl-v">C_l0_g0</span> <span class="pl-v">C_l0_g1</span>
<span class="pl-v">R0</span>      <span class="pl-v">C_l0_g0</span>                
<span class="pl-v">R_l0_g0</span> <span class="pl-v">R0C0</span>       <span class="pl-v">R0C0</span>    <span class="pl-v">R0C1</span>
<span class="pl-v">R_l0_g1</span> <span class="pl-v">R1C0</span>       <span class="pl-v">R1C0</span>    <span class="pl-v">R1C1</span>
<span class="pl-v">R_l0_g2</span> <span class="pl-v">R2C0</span>       <span class="pl-v">R2C0</span>    <span class="pl-v">R2C1</span>
<span class="pl-v">R_l0_g3</span> <span class="pl-v">R3C0</span>       <span class="pl-v">R3C0</span>    <span class="pl-v">R3C1</span>

<span class="pl-v">In</span> [<span class="pl-c1">70</span>]: <span class="pl-s1">from</span> <span class="pl-s1">pandas</span>.<span class="pl-s1">util</span>.<span class="pl-s1">testing</span> <span class="pl-s1">import</span> <span class="pl-s1">makeCustomDataframe</span> <span class="pl-k">as</span> <span class="pl-s1">mkdf</span>
    ...: <span class="pl-en">mkdf</span>(<span class="pl-c1">4</span>,<span class="pl-c1">2</span>,<span class="pl-s1">r_idx_nlevels</span><span class="pl-c1">=</span><span class="pl-c1">1</span>).<span class="pl-en">set_index</span>(<span class="pl-s">"C_l0_g0"</span>,<span class="pl-s1">append</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,<span class="pl-s1">drop</span><span class="pl-c1">=</span><span class="pl-c1">False</span>).<span class="pl-en">reset_index</span>(<span class="pl-c1">0</span>)
<span class="pl-v">Out</span>[<span class="pl-c1">70</span>]: 
<span class="pl-v">C0</span>            <span class="pl-v">R0</span> <span class="pl-v">C_l0_g0</span> <span class="pl-v">C_l0_g1</span>
<span class="pl-v">C_l0_g0</span>                         
<span class="pl-v">R0C0</span>     <span class="pl-v">R_l0_g0</span>    <span class="pl-v">R0C0</span>    <span class="pl-v">R0C1</span>
<span class="pl-v">R1C0</span>     <span class="pl-v">R_l0_g1</span>    <span class="pl-v">R1C0</span>    <span class="pl-v">R1C1</span>
<span class="pl-v">R2C0</span>     <span class="pl-v">R_l0_g2</span>    <span class="pl-v">R2C0</span>    <span class="pl-v">R2C1</span>
<span class="pl-v">R3C0</span>     <span class="pl-v">R_l0_g3</span>    <span class="pl-v">R3C0</span>    <span class="pl-v">R3C1</span></pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="In [71]: from pandas.util.testing import makeCustomDataframe as mkdf
    ...: mkdf(4,2,r_idx_nlevels=1).set_index(&quot;C_l0_g0&quot;,append=True,drop=False).reset_index(1)

/home/user1/src/pandas/pandas/core/internals.pyc in insert(self, loc, item, value)
    956     def insert(self, loc, item, value):
    957         if item in self.items:
--&gt; 958             raise Exception('cannot insert %s, already exists' % item)
    959 
    960         new_items = self.items.insert(loc, item)

Exception: cannot insert C_l0_g0, already exists"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-c1">71</span>]: <span class="pl-s1">from</span> <span class="pl-s1">pandas</span>.<span class="pl-s1">util</span>.<span class="pl-s1">testing</span> <span class="pl-s1">import</span> <span class="pl-s1">makeCustomDataframe</span> <span class="pl-k">as</span> <span class="pl-s1">mkdf</span>
    ...: <span class="pl-en">mkdf</span>(<span class="pl-c1">4</span>,<span class="pl-c1">2</span>,<span class="pl-s1">r_idx_nlevels</span><span class="pl-c1">=</span><span class="pl-c1">1</span>).<span class="pl-en">set_index</span>(<span class="pl-s">"C_l0_g0"</span>,<span class="pl-s1">append</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,<span class="pl-s1">drop</span><span class="pl-c1">=</span><span class="pl-c1">False</span>).<span class="pl-en">reset_index</span>(<span class="pl-c1">1</span>)

<span class="pl-c1">/</span><span class="pl-s1">home</span><span class="pl-c1">/</span><span class="pl-s1">user1</span><span class="pl-c1">/</span><span class="pl-s1">src</span><span class="pl-c1">/</span><span class="pl-s1">pandas</span><span class="pl-c1">/</span><span class="pl-s1">pandas</span><span class="pl-c1">/</span><span class="pl-s1">core</span><span class="pl-c1">/</span><span class="pl-s1">internals</span>.<span class="pl-s1">pyc</span> <span class="pl-c1">in</span> <span class="pl-en">insert</span>(<span class="pl-s1">self</span>, <span class="pl-s1">loc</span>, <span class="pl-s1">item</span>, <span class="pl-s1">value</span>)
    <span class="pl-c1">956</span>     <span class="pl-k">def</span> <span class="pl-en">insert</span>(<span class="pl-s1">self</span>, <span class="pl-s1">loc</span>, <span class="pl-s1">item</span>, <span class="pl-s1">value</span>):
    <span class="pl-c1">957</span>         <span class="pl-k">if</span> <span class="pl-s1">item</span> <span class="pl-c1">in</span> <span class="pl-s1">self</span>.<span class="pl-s1">items</span>:
<span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">&gt;</span> <span class="pl-c1">958</span>             <span class="pl-s1">raise</span> <span class="pl-v">Exception</span>(<span class="pl-s">'cannot insert %s, already exists'</span> <span class="pl-c1">%</span> <span class="pl-s1">item</span>)
    <span class="pl-c1">959</span> 
    <span class="pl-c1">960</span>         <span class="pl-s1">new_items</span> <span class="pl-c1">=</span> <span class="pl-s1">self</span>.<span class="pl-s1">items</span>.<span class="pl-en">insert</span>(<span class="pl-s1">loc</span>, <span class="pl-s1">item</span>)

<span class="pl-v">Exception</span>: <span class="pl-s1">cannot</span> <span class="pl-s1">insert</span> <span class="pl-v">C_l0_g0</span>, <span class="pl-s1">already</span> <span class="pl-s1">exists</span></pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="In [72]: from pandas.util.testing import makeCustomDataframe as mkdf
    ...: mkdf(4,2,r_idx_nlevels=1).set_index(&quot;C_l0_g0&quot;,append=True,drop=False).reset_index(-1)

/home/user1/src/pandas/pandas/core/internals.pyc in insert(self, loc, item, value)
    956     def insert(self, loc, item, value):
    957         if item in self.items:
--&gt; 958             raise Exception('cannot insert %s, already exists' % item)
    959 
    960         new_items = self.items.insert(loc, item)

Exception: cannot insert C_l0_g0, already exists
"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-c1">72</span>]: <span class="pl-s1">from</span> <span class="pl-s1">pandas</span>.<span class="pl-s1">util</span>.<span class="pl-s1">testing</span> <span class="pl-s1">import</span> <span class="pl-s1">makeCustomDataframe</span> <span class="pl-k">as</span> <span class="pl-s1">mkdf</span>
    ...: <span class="pl-en">mkdf</span>(<span class="pl-c1">4</span>,<span class="pl-c1">2</span>,<span class="pl-s1">r_idx_nlevels</span><span class="pl-c1">=</span><span class="pl-c1">1</span>).<span class="pl-en">set_index</span>(<span class="pl-s">"C_l0_g0"</span>,<span class="pl-s1">append</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,<span class="pl-s1">drop</span><span class="pl-c1">=</span><span class="pl-c1">False</span>).<span class="pl-en">reset_index</span>(<span class="pl-c1">-</span><span class="pl-c1">1</span>)

<span class="pl-c1">/</span><span class="pl-s1">home</span><span class="pl-c1">/</span><span class="pl-s1">user1</span><span class="pl-c1">/</span><span class="pl-s1">src</span><span class="pl-c1">/</span><span class="pl-s1">pandas</span><span class="pl-c1">/</span><span class="pl-s1">pandas</span><span class="pl-c1">/</span><span class="pl-s1">core</span><span class="pl-c1">/</span><span class="pl-s1">internals</span>.<span class="pl-s1">pyc</span> <span class="pl-c1">in</span> <span class="pl-en">insert</span>(<span class="pl-s1">self</span>, <span class="pl-s1">loc</span>, <span class="pl-s1">item</span>, <span class="pl-s1">value</span>)
    <span class="pl-c1">956</span>     <span class="pl-k">def</span> <span class="pl-en">insert</span>(<span class="pl-s1">self</span>, <span class="pl-s1">loc</span>, <span class="pl-s1">item</span>, <span class="pl-s1">value</span>):
    <span class="pl-c1">957</span>         <span class="pl-k">if</span> <span class="pl-s1">item</span> <span class="pl-c1">in</span> <span class="pl-s1">self</span>.<span class="pl-s1">items</span>:
<span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">&gt;</span> <span class="pl-c1">958</span>             <span class="pl-s1">raise</span> <span class="pl-v">Exception</span>(<span class="pl-s">'cannot insert %s, already exists'</span> <span class="pl-c1">%</span> <span class="pl-s1">item</span>)
    <span class="pl-c1">959</span> 
    <span class="pl-c1">960</span>         <span class="pl-s1">new_items</span> <span class="pl-c1">=</span> <span class="pl-s1">self</span>.<span class="pl-s1">items</span>.<span class="pl-en">insert</span>(<span class="pl-s1">loc</span>, <span class="pl-s1">item</span>)

<span class="pl-v">Exception</span>: <span class="pl-s1">cannot</span> <span class="pl-s1">insert</span> <span class="pl-v">C_l0_g0</span>, <span class="pl-s1">already</span> <span class="pl-s1">exists</span></pre></div>