<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="In [1]: from collections import OrderedDict
In [2]: import pandas as pd
In [3]: pd.__version__
Out[3]: u'0.21.0'

# the following works as expected:
In [4]: df1 = pd.DataFrame([[1, 2, 3]], columns=['a', 'b', 'c'])
In [5]: df2 = pd.DataFrame(columns=['a', 'b', 'c'])
In [6]: pd.concat([df1, df2])
Out[6]: 
   a  b  c
0  1  2  3

# however, the following seems like it does an identical thing but throws an error:
In [7]: od3 = OrderedDict([('a', [1]), ('b', [2]), ('c', [3])])
In [8]: od4 = OrderedDict([('a', []), ('b', []), ('c', [])])
In [9]: df3 = pd.DataFrame(od3)
In [10]: df4 = pd.DataFrame(od4)
In [11]: pd.concat([df3, df4])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
&lt;ipython-input-11-ac4fae34c928&gt; in &lt;module&gt;()
----&gt; 1 pd.concat([df3, df4])
#...
ValueError: Shape of passed values is (3, 1), indices imply (3, 0)"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-c1">1</span>]: <span class="pl-s1">from</span> <span class="pl-s1">collections</span> <span class="pl-k">import</span> <span class="pl-v">OrderedDict</span>
<span class="pl-v">In</span> [<span class="pl-c1">2</span>]: <span class="pl-s1">import</span> <span class="pl-s1">pandas</span> <span class="pl-k">as</span> <span class="pl-s1">pd</span>
<span class="pl-v">In</span> [<span class="pl-c1">3</span>]: <span class="pl-s1">pd</span>.<span class="pl-s1">__version__</span>
<span class="pl-v">Out</span>[<span class="pl-c1">3</span>]: <span class="pl-s">u'0.21.0'</span>

<span class="pl-c"># the following works as expected:</span>
<span class="pl-v">In</span> [<span class="pl-c1">4</span>]: <span class="pl-s1">df1</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>([[<span class="pl-c1">1</span>, <span class="pl-c1">2</span>, <span class="pl-c1">3</span>]], <span class="pl-s1">columns</span><span class="pl-c1">=</span>[<span class="pl-s">'a'</span>, <span class="pl-s">'b'</span>, <span class="pl-s">'c'</span>])
<span class="pl-v">In</span> [<span class="pl-c1">5</span>]: <span class="pl-s1">df2</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-s">'a'</span>, <span class="pl-s">'b'</span>, <span class="pl-s">'c'</span>])
<span class="pl-v">In</span> [<span class="pl-c1">6</span>]: <span class="pl-s1">pd</span>.<span class="pl-en">concat</span>([<span class="pl-s1">df1</span>, <span class="pl-s1">df2</span>])
<span class="pl-v">Out</span>[<span class="pl-c1">6</span>]: 
   <span class="pl-s1">a</span>  <span class="pl-s1">b</span>  <span class="pl-s1">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-c"># however, the following seems like it does an identical thing but throws an error:</span>
<span class="pl-v">In</span> [<span class="pl-c1">7</span>]: <span class="pl-s1">od3</span> <span class="pl-c1">=</span> <span class="pl-v">OrderedDict</span>([(<span class="pl-s">'a'</span>, [<span class="pl-c1">1</span>]), (<span class="pl-s">'b'</span>, [<span class="pl-c1">2</span>]), (<span class="pl-s">'c'</span>, [<span class="pl-c1">3</span>])])
<span class="pl-v">In</span> [<span class="pl-c1">8</span>]: <span class="pl-s1">od4</span> <span class="pl-c1">=</span> <span class="pl-v">OrderedDict</span>([(<span class="pl-s">'a'</span>, []), (<span class="pl-s">'b'</span>, []), (<span class="pl-s">'c'</span>, [])])
<span class="pl-v">In</span> [<span class="pl-c1">9</span>]: <span class="pl-s1">df3</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-s1">od3</span>)
<span class="pl-v">In</span> [<span class="pl-c1">10</span>]: <span class="pl-s1">df4</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-s1">od4</span>)
<span class="pl-v">In</span> [<span class="pl-c1">11</span>]: <span class="pl-s1">pd</span>.<span class="pl-en">concat</span>([<span class="pl-s1">df3</span>, <span class="pl-s1">df4</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-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-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-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-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span>
<span class="pl-v">ValueError</span>                                <span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>)
<span class="pl-c1">&lt;</span><span class="pl-s1">ipython</span><span class="pl-c1">-</span><span class="pl-s1">input</span><span class="pl-c1">-</span><span class="pl-c1">11</span><span class="pl-c1">-</span><span class="pl-s1">ac4fae34c928</span><span class="pl-c1">&gt;</span> <span class="pl-s1">in</span> <span class="pl-c1">&lt;</span><span class="pl-s1">module</span><span class="pl-c1">&gt;</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">&gt;</span> <span class="pl-c1">1</span> <span class="pl-s1">pd</span>.<span class="pl-en">concat</span>([<span class="pl-s1">df3</span>, <span class="pl-s1">df4</span>])
<span class="pl-c">#...</span>
<span class="pl-v">ValueError</span>: <span class="pl-v">Shape</span> <span class="pl-s1">of</span> <span class="pl-s1">passed</span> <span class="pl-s1">values</span> <span class="pl-c1">is</span> (<span class="pl-c1">3</span>, <span class="pl-c1">1</span>), <span class="pl-s1">indices</span> <span class="pl-en">imply</span> (<span class="pl-c1">3</span>, <span class="pl-c1">0</span>)</pre></div>
<p dir="auto">Rewriting it in copy/pastable form...</p>
<p dir="auto">This works:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="df1 = pd.DataFrame([[1, 2, 3]], columns=['a', 'b', 'c'])
df2 = pd.DataFrame(columns=['a', 'b', 'c'])
pd.concat([df1, df2])"><pre class="notranslate"><span class="pl-s1">df1</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>([[<span class="pl-c1">1</span>, <span class="pl-c1">2</span>, <span class="pl-c1">3</span>]], <span class="pl-s1">columns</span><span class="pl-c1">=</span>[<span class="pl-s">'a'</span>, <span class="pl-s">'b'</span>, <span class="pl-s">'c'</span>])
<span class="pl-s1">df2</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-s">'a'</span>, <span class="pl-s">'b'</span>, <span class="pl-s">'c'</span>])
<span class="pl-s1">pd</span>.<span class="pl-en">concat</span>([<span class="pl-s1">df1</span>, <span class="pl-s1">df2</span>])</pre></div>
<p dir="auto">And this does not:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="od3 = OrderedDict([('a', [1]), ('b', [2]), ('c', [3])])
od4 = OrderedDict([('a', []), ('b', []), ('c', [])])
df3 = pd.DataFrame(od3)
df4 = pd.DataFrame(od4)
pd.concat([df3, df4])"><pre class="notranslate"><span class="pl-s1">od3</span> <span class="pl-c1">=</span> <span class="pl-v">OrderedDict</span>([(<span class="pl-s">'a'</span>, [<span class="pl-c1">1</span>]), (<span class="pl-s">'b'</span>, [<span class="pl-c1">2</span>]), (<span class="pl-s">'c'</span>, [<span class="pl-c1">3</span>])])
<span class="pl-s1">od4</span> <span class="pl-c1">=</span> <span class="pl-v">OrderedDict</span>([(<span class="pl-s">'a'</span>, []), (<span class="pl-s">'b'</span>, []), (<span class="pl-s">'c'</span>, [])])
<span class="pl-s1">df3</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-s1">od3</span>)
<span class="pl-s1">df4</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-s1">od4</span>)
<span class="pl-s1">pd</span>.<span class="pl-en">concat</span>([<span class="pl-s1">df3</span>, <span class="pl-s1">df4</span>])</pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">This is also described <a href="https://stackoverflow.com/questions/47194806/pandas-inconsistency-in-concat-behavior" rel="nofollow">here</a>.</p>
<p dir="auto">In the above code, <code class="notranslate">df1</code> equals <code class="notranslate">df3</code>, and <code class="notranslate">df2</code> and <code class="notranslate">df4</code> are both empty dataframes with the same column names (although, strangely, <code class="notranslate">df2</code> and <code class="notranslate">df4</code> aren't equal according to <code class="notranslate">df2.equals(df4)</code>) but <code class="notranslate">pd.concat([df1, df2])</code> works while <code class="notranslate">pd.concat([df3, df4])</code>results in <code class="notranslate">ValueError</code>.  This did not happen in previous versions of Pandas, but when I upgraded to 0.21.0, it started happening.</p>
<p dir="auto">Oddly, as the stackoverflow link notes, using the <code class="notranslate">drop_duplicates()</code> method on either <code class="notranslate">df3</code> or <code class="notranslate">df4</code> (or both) results in the <code class="notranslate">concat()</code> working, even though neither of them contains any duplicates.</p>
<h4 dir="auto">Expected Output</h4>
<p dir="auto">The expected output of <code class="notranslate">pd.concat([df3, df4])</code> is</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="   a  b  c
0  1  2  3"><pre class="notranslate">   <span class="pl-s1">a</span>  <span class="pl-s1">b</span>  <span class="pl-s1">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></pre></div>
<h4 dir="auto">Output of <code class="notranslate">pd.show_versions()</code></h4>
<details>
<p dir="auto">[paste the output of <code class="notranslate">pd.show_versions()</code> here below this line]</p>
<h2 dir="auto">INSTALLED VERSIONS</h2>
<p dir="auto">commit: None<br>
python: 2.7.13.final.0<br>
python-bits: 64<br>
OS: Darwin<br>
OS-release: 16.7.0<br>
machine: x86_64<br>
processor: i386<br>
byteorder: little<br>
LC_ALL: None<br>
LANG: en_US.UTF-8<br>
LOCALE: None.None</p>
<p dir="auto">pandas: 0.21.0<br>
pytest: 3.2.1<br>
pip: 9.0.1<br>
setuptools: 32.1.0<br>
Cython: 0.23.4<br>
numpy: 1.13.3<br>
scipy: 0.19.1<br>
pyarrow: None<br>
xarray: None<br>
IPython: 5.3.0<br>
sphinx: None<br>
patsy: 0.4.1<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: 2.0.2<br>
openpyxl: None<br>
xlrd: None<br>
xlwt: None<br>
xlsxwriter: None<br>
lxml: None<br>
bs4: 4.6.0<br>
html5lib: 0.999999999<br>
sqlalchemy: 1.1.14<br>
pymysql: 0.7.11.None<br>
psycopg2: 2.7.3.1 (dt dec pq3 ext lo64)<br>
jinja2: 2.9.6<br>
s3fs: None<br>
fastparquet: None<br>
pandas_gbq: None<br>
pandas_datareader: 0.5.0</p>
</details>
<p dir="auto">Have you ever written code that looks like this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="if isinstance(d.index, MultiIndex):
    results = []
    for l in d.index.levels:
       for x in baz(l):
          results.append(foo)
elif  isinstance(d.index, Index):
    for x in d.index:
       foo"><pre class="notranslate"><code class="notranslate">if isinstance(d.index, MultiIndex):
    results = []
    for l in d.index.levels:
       for x in baz(l):
          results.append(foo)
elif  isinstance(d.index, Index):
    for x in d.index:
       foo
</code></pre></div>
<p dir="auto">I've had to special case the handling of index vs. multindex several times in the past.<br>
Conceptually, I should be able to treat index as a private case of MultIndex<br>
with nlevels =1, and supporting that in the API would make things nicer.</p>
<hr>
<p dir="auto"><strong>Edit by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/cpcloud/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/cpcloud">@cpcloud</a>:</strong><br>
Tasks :</p>
<h3 dir="auto">API Unification</h3>
<p dir="auto">Method unification is relatively simple:</p>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox">  <code class="notranslate">Index.from_tuples</code> and <code class="notranslate">Index.from_arrays</code> are just <code class="notranslate">MultiIndex.from_tuples</code> and <code class="notranslate">MultiIndex.from_arrays</code> moved to classmethods of <code class="notranslate">Index</code>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">droplevel</code>, ` just raises on Index (right? what would it mean?): <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="324283112" data-permission-text="Title is private" data-url="https://github.com/pandas-dev/pandas/issues/21115" data-hovercard-type="issue" data-hovercard-url="/pandas-dev/pandas/issues/21115/hovercard" href="https://github.com/pandas-dev/pandas/issues/21115">#21115</a></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">has_duplicates</code> is straightforward</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">truncate</code> should be equivalent to slicing</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">reorder_levels</code> raises if not level=0 or name of index</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">equal_levels</code> - straightforward</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">levshape</code> - (len(ind),)</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">sortorder</code> - None</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">get_loc_level</code> - I think meaningless with tuple, raises whatever if not 0 or index name</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">is_lexsorted</code> - doesn't need to change</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">is_lexosrted_tuple</code> - doesn't need to change</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">is_monotonic_*</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">lexsort_depth</code> - doesn't need to be changed at all</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">searchsorted</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">repeat</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> <code class="notranslate">levels</code> and <code class="notranslate">labels</code> property for Index - question on whether it should be sorted.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> change to <code class="notranslate">rename</code> behavior: <code class="notranslate">Index</code> will accept either string or single-element list; MI continues to handle only list</li>
</ul>