Skip to content

Commit 219bdcb

Browse files
committed
BUG: fix to_html with colums MultiIndex without level names, close pandas-dev#1053
1 parent b3f2133 commit 219bdcb

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

pandas/core/format.py

+4
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ def _column_header():
262262
if isinstance(self.columns, MultiIndex):
263263
if self.has_column_names:
264264
row.append(single_column_table(self.columns.names))
265+
else:
266+
row.append('')
265267
row.extend([single_column_table(c) for c in self.columns])
266268
else:
267269
row.append(self.columns.name or '')
@@ -290,9 +292,11 @@ def _column_header():
290292
row = frame.index.names + [''] * len(self.columns)
291293
write_tr(row, indent, indent_delta, header=True)
292294

295+
indent -= indent_delta
293296
write('</thead>', indent)
294297

295298
write('<tbody>', indent)
299+
indent += indent_delta
296300

297301
_bold_row = self.kwds.get('bold_rows', False)
298302
def _maybe_bold_row(x):

pandas/tests/test_format.py

+77
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,83 @@ def test_to_html_columns_arg(self):
386386
result = self.frame.to_html(columns=['A'])
387387
self.assert_('<th>B</th>' not in result)
388388

389+
def test_to_html_multiindex(self):
390+
columns = pandas.MultiIndex.from_tuples(zip(range(4),
391+
np.mod(range(4), 2)),
392+
names=['CL0', 'CL1'])
393+
df = pandas.DataFrame([list('abcd'), list('efgh')], columns=columns)
394+
result = df.to_html()
395+
expected = ('<table border="1">\n'
396+
' <thead>\n'
397+
' <tr>\n'
398+
' <th><table><tbody><tr><td>CL0</td></tr><tr>'
399+
'<td>CL1</td></tr></tbody></table></th>\n'
400+
' <th><table><tbody><tr><td>0</td></tr><tr>'
401+
'<td>0</td></tr></tbody></table></th>\n'
402+
' <th><table><tbody><tr><td>1</td></tr><tr>'
403+
'<td>1</td></tr></tbody></table></th>\n'
404+
' <th><table><tbody><tr><td>2</td></tr><tr>'
405+
'<td>0</td></tr></tbody></table></th>\n'
406+
' <th><table><tbody><tr><td>3</td></tr><tr>'
407+
'<td>1</td></tr></tbody></table></th>\n'
408+
' </tr>\n'
409+
' </thead>\n'
410+
' <tbody>\n'
411+
' <tr>\n'
412+
' <td><strong>0</strong></td>\n'
413+
' <td> a</td>\n'
414+
' <td> b</td>\n'
415+
' <td> c</td>\n'
416+
' <td> d</td>\n'
417+
' </tr>\n'
418+
' <tr>\n'
419+
' <td><strong>1</strong></td>\n'
420+
' <td> e</td>\n'
421+
' <td> f</td>\n'
422+
' <td> g</td>\n'
423+
' <td> h</td>\n'
424+
' </tr>\n'
425+
' </tbody>\n'
426+
'</table>')
427+
self.assertEqual(result, expected)
428+
429+
columns = pandas.MultiIndex.from_tuples(zip(range(4),
430+
np.mod(range(4), 2)))
431+
df = pandas.DataFrame([list('abcd'), list('efgh')], columns=columns)
432+
result = df.to_html()
433+
expected = ('<table border="1">\n'
434+
' <thead>\n'
435+
' <tr>\n'
436+
' <th></th>\n'
437+
' <th><table><tbody><tr><td>0</td></tr>'
438+
'<tr><td>0</td></tr></tbody></table></th>\n'
439+
' <th><table><tbody><tr><td>1</td></tr>'
440+
'<tr><td>1</td></tr></tbody></table></th>\n'
441+
' <th><table><tbody><tr><td>2</td></tr>'
442+
'<tr><td>0</td></tr></tbody></table></th>\n'
443+
' <th><table><tbody><tr><td>3</td></tr>'
444+
'<tr><td>1</td></tr></tbody></table></th>\n'
445+
' </tr>\n'
446+
' </thead>\n'
447+
' <tbody>\n'
448+
' <tr>\n'
449+
' <td><strong>0</strong></td>\n'
450+
' <td> a</td>\n'
451+
' <td> b</td>\n'
452+
' <td> c</td>\n'
453+
' <td> d</td>\n'
454+
' </tr>\n'
455+
' <tr>\n'
456+
' <td><strong>1</strong></td>\n'
457+
' <td> e</td>\n'
458+
' <td> f</td>\n'
459+
' <td> g</td>\n'
460+
' <td> h</td>\n'
461+
' </tr>\n'
462+
' </tbody>\n'
463+
'</table>')
464+
self.assertEqual(result, expected)
465+
389466
def test_repr_html(self):
390467
self.frame._repr_html_()
391468

0 commit comments

Comments
 (0)