Repository: pandas-dev/pandas

Issue:
to_csv() with a single level row MultiIndex does not produce the desired output
#### Code Sample, a copy-pastable example if possible

```python
>>> import pandas as pd; 
>>> idx_1d = pd.MultiIndex(levels=[[1.0]], labels=[[0]], names=['x'])
>>> idx_2d = pd.MultiIndex(levels=[[1.], [2.]], labels=[[0], [0]], names=['x', 'y'])

# DataFrame
>>> print(pd.DataFrame({'data': [1]}, idx_2d).to_csv())
x,y,data
1.0,2.0,1

>>> print(pd.DataFrame({'data': [1]}, idx_1d).to_csv())
x,data
"('1.0',)",1

# Series
>>> print(pd.Series([1], idx_2d).to_csv())
1.0,2.0,1

>>> print(pd.Series([1], idx_1d).to_csv())
"('1.0',)",1

```
#### Problem description
The output for `index.nlevels==1` should be the same as for `index.nlevels==2`, with one column less. That matches the output from other index types and was the output produced by pandas up to 0.20.3.

#### Expected Output
```python
>>> print(pd.DataFrame({'data': [1]}, idx_1d).to_csv())
x,data
1.0,1

>>> print(pd.Series([1], idx_1d).to_csv())
1.0,1
```
#### Output of ``pd.show_versions()``

<details>
INSTALLED VERSIONS
------------------
commit: None
python: 3.6.0.final.0
python-bits: 64
OS: Windows
OS-release: 7
machine: AMD64
processor: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.22.0
pytest: 3.2.1
pip: 9.0.1
setuptools: 27.2.0
Cython: 0.25.2
numpy: 1.11.3
scipy: 0.19.0
pyarrow: None
xarray: None
IPython: 5.1.0
sphinx: 1.5.1
patsy: 0.4.1
dateutil: 2.6.0
pytz: 2016.10
blosc: None
bottleneck: 1.2.0
tables: 3.4.2
numexpr: 2.6.1
feather: None
matplotlib: 2.0.0
openpyxl: 2.4.1
xlrd: 1.0.0
xlwt: 1.2.0
xlsxwriter: 0.9.6
lxml: 4.1.1
bs4: 4.5.3
html5lib: None
sqlalchemy: 1.1.5
pymysql: None
psycopg2: None
jinja2: 2.9.4
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
</details>



Discussion:
cc @gfyoung 
@joe1gi : Thanks for the report!  I agree: the outputs should match.  PR to patch is welcome!

Resolving patch:
diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py
--- a/pandas/core/indexes/multi.py
+++ b/pandas/core/indexes/multi.py
@@ -732,11 +732,14 @@ def _format_native_types(self, na_rep='nan', **kwargs):
             new_levels.append(level)
             new_labels.append(label)
 
-        # reconstruct the multi-index
-        mi = MultiIndex(levels=new_levels, labels=new_labels, names=self.names,
-                        sortorder=self.sortorder, verify_integrity=False)
-
-        return mi.values
+        if len(new_levels) == 1:
+            return Index(new_levels[0])._format_native_types()
+        else:
+            # reconstruct the multi-index
+            mi = MultiIndex(levels=new_levels, labels=new_labels,
+                            names=self.names, sortorder=self.sortorder,
+                            verify_integrity=False)
+            return mi.values
 
     @Appender(_index_shared_docs['_get_grouper_for_level'])
     def _get_grouper_for_level(self, mapper, level):


Test patch:
diff --git a/pandas/tests/io/formats/test_to_csv.py b/pandas/tests/io/formats/test_to_csv.py
--- a/pandas/tests/io/formats/test_to_csv.py
+++ b/pandas/tests/io/formats/test_to_csv.py
@@ -325,6 +325,25 @@ def test_to_csv_multi_index(self):
         exp = tm.convert_rows_list_to_csv_str(exp_rows)
         assert df.to_csv(index=False) == exp
 
+    @pytest.mark.parametrize("ind,expected", [
+        (pd.MultiIndex(levels=[[1.0]],
+                       labels=[[0]],
+                       names=["x"]),
+         "x,data\n1.0,1\n"),
+        (pd.MultiIndex(levels=[[1.], [2.]],
+                       labels=[[0], [0]],
+                       names=["x", "y"]),
+         "x,y,data\n1.0,2.0,1\n")
+    ])
+    @pytest.mark.parametrize("klass", [
+        pd.DataFrame, pd.Series
+    ])
+    def test_to_csv_single_level_multi_index(self, ind, expected, klass):
+        # see gh-19589
+        result = klass(pd.Series([1], ind, name="data")).to_csv(
+            line_terminator="\n", header=True)
+        assert result == expected
+
     def test_to_csv_string_array_ascii(self):
         # GH 10813
         str_array = [{'names': ['foo', 'bar']}, {'names': ['baz', 'qux']}]