Skip to content

Commit a97113c

Browse files
committed
ENH: Raise error on trying to write excel file with a MultiIndexed DataFrame. closes pandas-dev#9794
1 parent cef3c85 commit a97113c

File tree

3 files changed

+51
-26
lines changed

3 files changed

+51
-26
lines changed

doc/source/whatsnew/v0.16.1.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ Enhancements
5353

5454
- Allow timedelta string conversion when leading zero is missing from time definition, ie `0:00:00` vs `00:00:00`. (:issue:`9570`)
5555

56+
- Trying to write an excel file now raises ``NotImplementedError`` if the ``DataFrame`` has a ``MultiIndex`` instead of writing a broken Excel file. (:issue:`9794`)
57+
5658
.. _whatsnew_0161.api:
5759

5860
API changes
@@ -137,7 +139,6 @@ Bug Fixes
137139

138140

139141
- Bug in unequal comparisons between categorical data and a scalar, which was not in the categories (e.g. ``Series(Categorical(list("abc"), ordered=True)) > "d"``. This returned ``False`` for all elements, but now raises a ``TypeError``. Equality comparisons also now return ``False`` for ``==`` and ``True`` for ``!=``. (:issue:`9848`)
140-
141142
- Bug in DataFrame ``__setitem__`` when right hand side is a dictionary (:issue:`9874`)
142143
- Bug in ``where`` when dtype is ``datetime64/timedelta64``, but dtype of other is not (:issue:`9804`)
143144
- Bug in ``MultiIndex.sortlevel()`` results in unicode level name breaks (:issue:`9875`)

pandas/core/frame.py

+3
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,9 @@ def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='',
12441244
>>> writer.save()
12451245
"""
12461246
from pandas.io.excel import ExcelWriter
1247+
if self.columns.nlevels > 1:
1248+
raise NotImplementedError("Writing as Excel with a MultiIndex is "
1249+
"not yet implemented.")
12471250

12481251
need_save = False
12491252
if encoding == None:

pandas/io/tests/test_excel.py

+46-25
Original file line numberDiff line numberDiff line change
@@ -1132,31 +1132,29 @@ def roundtrip(df, header=True, parser_hdr=0):
11321132

11331133
nrows = 5
11341134
ncols = 3
1135-
1136-
for i in range(1, 4): # row multindex upto nlevel=3
1137-
for j in range(1, 4): # col ""
1138-
df = mkdf(nrows, ncols, r_idx_nlevels=i, c_idx_nlevels=j)
1139-
res = roundtrip(df)
1140-
# shape
1141-
self.assertEqual(res.shape, (nrows, ncols + i))
1142-
1143-
# no nans
1144-
for r in range(len(res.index)):
1145-
for c in range(len(res.columns)):
1146-
self.assertTrue(res.ix[r, c] is not np.nan)
1147-
1148-
for i in range(1, 4): # row multindex upto nlevel=3
1149-
for j in range(1, 4): # col ""
1150-
df = mkdf(nrows, ncols, r_idx_nlevels=i, c_idx_nlevels=j)
1151-
res = roundtrip(df, False)
1152-
# shape
1153-
self.assertEqual(res.shape, (
1154-
nrows - 1, ncols + i)) # first row taken as columns
1155-
1156-
# no nans
1157-
for r in range(len(res.index)):
1158-
for c in range(len(res.columns)):
1159-
self.assertTrue(res.ix[r, c] is not np.nan)
1135+
for use_headers in (True, False):
1136+
for i in range(1, 4): # row multindex upto nlevel=3
1137+
for j in range(1, 4): # col ""
1138+
df = mkdf(nrows, ncols, r_idx_nlevels=i, c_idx_nlevels=j)
1139+
1140+
#this if will be removed once multi column excel writing
1141+
#is implemented for now fixing #9794
1142+
if j>1:
1143+
with tm.assertRaises(NotImplementedError):
1144+
res = roundtrip(df, use_headers)
1145+
else:
1146+
res = roundtrip(df, use_headers)
1147+
1148+
if use_headers:
1149+
self.assertEqual(res.shape, (nrows, ncols + i))
1150+
else:
1151+
# first row taken as columns
1152+
self.assertEqual(res.shape, (nrows - 1, ncols + i))
1153+
1154+
# no nans
1155+
for r in range(len(res.index)):
1156+
for c in range(len(res.columns)):
1157+
self.assertTrue(res.ix[r, c] is not np.nan)
11601158

11611159
res = roundtrip(DataFrame([0]))
11621160
self.assertEqual(res.shape, (1, 1))
@@ -1394,6 +1392,29 @@ class XlwtTests(ExcelWriterBase, tm.TestCase):
13941392
engine_name = 'xlwt'
13951393
check_skip = staticmethod(_skip_if_no_xlwt)
13961394

1395+
def test_excel_raise_not_implemented_error_on_multiindex_columns(self):
1396+
_skip_if_no_xlwt()
1397+
#MultiIndex as columns is not yet implemented 9794
1398+
cols = pd.MultiIndex.from_tuples([('site',''),
1399+
('2014','height'),
1400+
('2014','weight')])
1401+
df = pd.DataFrame(np.random.randn(10,3), columns=cols)
1402+
with tm.assertRaises(NotImplementedError):
1403+
with ensure_clean(self.ext) as path:
1404+
df.to_excel(path, index=False)
1405+
1406+
def test_excel_multiindex_index(self):
1407+
_skip_if_no_xlwt()
1408+
#MultiIndex as index works so assert no error #9794
1409+
cols = pd.MultiIndex.from_tuples([('site',''),
1410+
('2014','height'),
1411+
('2014','weight')])
1412+
df = pd.DataFrame(np.random.randn(3,10), index=cols)
1413+
with ensure_clean(self.ext) as path:
1414+
df.to_excel(path, index=False)
1415+
1416+
1417+
13971418
def test_to_excel_styleconverter(self):
13981419
_skip_if_no_xlwt()
13991420

0 commit comments

Comments
 (0)