<h4 dir="auto">Code Sample, a copy-pastable example if possible</h4>
<p dir="auto">using pandas 0.22:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: object_data = ['silly walks', np.nan, 'dead parrot']

In [4]: pd.Series(object_data, dtype=object)
Out[4]:
0    silly walks
1            NaN
2    dead parrot
dtype: object

In [5]: pd.Series(object_data, dtype=str)
Out[5]:
0    silly walks
1            NaN
2    dead parrot
dtype: object"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-c1">1</span>]: <span class="pl-s1">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</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">object_data</span> <span class="pl-c1">=</span> [<span class="pl-s">'silly walks'</span>, <span class="pl-s1">np</span>.<span class="pl-s1">nan</span>, <span class="pl-s">'dead parrot'</span>]

<span class="pl-v">In</span> [<span class="pl-c1">4</span>]: <span class="pl-s1">pd</span>.<span class="pl-v">Series</span>(<span class="pl-s1">object_data</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">object</span>)
<span class="pl-v">Out</span>[<span class="pl-c1">4</span>]:
<span class="pl-c1">0</span>    <span class="pl-s1">silly</span> <span class="pl-s1">walks</span>
<span class="pl-c1">1</span>            <span class="pl-v">NaN</span>
<span class="pl-c1">2</span>    <span class="pl-s1">dead</span> <span class="pl-s1">parrot</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">object</span>

<span class="pl-v">In</span> [<span class="pl-c1">5</span>]: <span class="pl-s1">pd</span>.<span class="pl-v">Series</span>(<span class="pl-s1">object_data</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">str</span>)
<span class="pl-v">Out</span>[<span class="pl-c1">5</span>]:
<span class="pl-c1">0</span>    <span class="pl-s1">silly</span> <span class="pl-s1">walks</span>
<span class="pl-c1">1</span>            <span class="pl-v">NaN</span>
<span class="pl-c1">2</span>    <span class="pl-s1">dead</span> <span class="pl-s1">parrot</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">object</span></pre></div>
<p dir="auto">using pandas 0.23:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: object_data = ['silly walks', np.nan, 'dead parrot']

In [4]: pd.Series(object_data, dtype=object)
Out[4]:
0    silly walks
1            NaN
2    dead parrot
dtype: object

In [5]: pd.Series(object_data, dtype=str)
Out[5]:
0    silly walks
1            nan
2    dead parrot
dtype: object"><pre class="notranslate"><span class="pl-v">In</span> [<span class="pl-c1">1</span>]: <span class="pl-s1">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</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">object_data</span> <span class="pl-c1">=</span> [<span class="pl-s">'silly walks'</span>, <span class="pl-s1">np</span>.<span class="pl-s1">nan</span>, <span class="pl-s">'dead parrot'</span>]

<span class="pl-v">In</span> [<span class="pl-c1">4</span>]: <span class="pl-s1">pd</span>.<span class="pl-v">Series</span>(<span class="pl-s1">object_data</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">object</span>)
<span class="pl-v">Out</span>[<span class="pl-c1">4</span>]:
<span class="pl-c1">0</span>    <span class="pl-s1">silly</span> <span class="pl-s1">walks</span>
<span class="pl-c1">1</span>            <span class="pl-v">NaN</span>
<span class="pl-c1">2</span>    <span class="pl-s1">dead</span> <span class="pl-s1">parrot</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">object</span>

<span class="pl-v">In</span> [<span class="pl-c1">5</span>]: <span class="pl-s1">pd</span>.<span class="pl-v">Series</span>(<span class="pl-s1">object_data</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">str</span>)
<span class="pl-v">Out</span>[<span class="pl-c1">5</span>]:
<span class="pl-c1">0</span>    <span class="pl-s1">silly</span> <span class="pl-s1">walks</span>
<span class="pl-c1">1</span>            <span class="pl-s1">nan</span>
<span class="pl-c1">2</span>    <span class="pl-s1">dead</span> <span class="pl-s1">parrot</span>
<span class="pl-s1">dtype</span>: <span class="pl-s1">object</span></pre></div>
<h4 dir="auto">Problem description</h4>
<p dir="auto">as of v0.23, when provided with the <code class="notranslate">str</code> dtype, a <code class="notranslate">np.nan</code> in a list of values gets converter to the string <code class="notranslate">nan</code>.</p>
<p dir="auto"><a href="http://pandas.pydata.org/pandas-docs/stable/basics.html#dtypes" rel="nofollow">the docs don't specify <code class="notranslate">str</code> as a valid dtype in the first place </a>, so perhaps the problem here is that pandas should be stricter and check that the provided dtype is supported? Or the docs could mention that a custom conversion function can be passed? either way this caused test failures on <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="328034320" data-permission-text="Title is private" data-url="https://github.com/clembou/behave-pandas/issues/7" data-hovercard-type="pull_request" data-hovercard-url="/clembou/behave-pandas/pull/7/hovercard" href="https://github.com/clembou/behave-pandas/pull/7">clembou/behave-pandas#7</a>, so I thought I'd raise an issue as I might not be the only one affected.</p>
<p dir="auto">Feel free to close if you think this is simply an unsupported use of the <code class="notranslate">dtype</code> parameter.</p>
<h4 dir="auto">Output of <code class="notranslate">pd.show_versions()</code></h4>
<details>
INSTALLED VERSIONS
------------------
commit: None
python: 3.6.5.final.0
python-bits: 64
OS: Darwin
OS-release: 17.5.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: None
LANG: en_GB.UTF-8
LOCALE: en_GB.UTF-8
<p dir="auto">pandas: 0.23.0<br>
pytest: None<br>
pip: 10.0.1<br>
setuptools: 39.2.0<br>
Cython: None<br>
numpy: 1.14.3<br>
scipy: None<br>
pyarrow: None<br>
xarray: None<br>
IPython: 6.4.0<br>
sphinx: None<br>
patsy: None<br>
dateutil: 2.7.3<br>
pytz: 2018.4<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>
<p dir="auto">As far as I can tell, both methods of reading an Excel sheet (through ExcelFile and read_excel) do not have the option to avoid mangling duplicate columns, which exists for read_csv (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="13708937" data-permission-text="Title is private" data-url="https://github.com/pandas-dev/pandas/issues/3468" data-hovercard-type="issue" data-hovercard-url="/pandas-dev/pandas/issues/3468/hovercard" href="https://github.com/pandas-dev/pandas/issues/3468">#3468</a>).</p>
<p dir="auto">I have an Excel file that looks like this:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="  foo  foo  bar  bar  baz  baz
    A    B    A    B    A    B
  123  456  789   12  345  678
  901  234  567  890  123  456
  789   12  345  678  901  234"><pre class="notranslate"><code class="notranslate">  foo  foo  bar  bar  baz  baz
    A    B    A    B    A    B
  123  456  789   12  345  678
  901  234  567  890  123  456
  789   12  345  678  901  234
</code></pre></div>
<p dir="auto">I initially encountered this problem while trying to find a workaround for not being able to specify a multirow-header (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="18575759" data-permission-text="Title is private" data-url="https://github.com/pandas-dev/pandas/issues/4679" data-hovercard-type="issue" data-hovercard-url="/pandas-dev/pandas/issues/4679/hovercard" href="https://github.com/pandas-dev/pandas/issues/4679">#4679</a>). Reading in this Excel file with header = 0 (default) mangles the column names:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; df = pd.read_excel(&quot;dupe_cols.xlsx&quot;, header = 0)
&gt;&gt;&gt; print df
   foo foo.1  bar bar.1  baz baz.1
0    A     B    A     B    A     B
1  123   456  789    12  345   678
2  901   234  567   890  123   456
3  789    12  345   678  901   234"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; df = pd.read_excel("dupe_cols.xlsx", header = 0)
&gt;&gt;&gt; print df
   foo foo.1  bar bar.1  baz baz.1
0    A     B    A     B    A     B
1  123   456  789    12  345   678
2  901   234  567   890  123   456
3  789    12  345   678  901   234
</code></pre></div>
<p dir="auto">Unlike <code class="notranslate">read_csv</code>, <code class="notranslate">read_excel</code> does not have the option to avoid mangling duplicate columns (using ExcelFile.parse works the same as far as I can see). Specifying header = None in <code class="notranslate">read_excel</code> and then assigning the column names to the first row will effectively allow you to avoid mangling the column names. You could also read in the Excel sheet with header = None, save a .csv with header = False and index = False, then read that csv and specify mangle_dupe_cols = False to get the dataframe you want. (Incidentally, this also allows you to specify multiple rows as the header, which is the behavior I was originally trying to emulate.)</p>