Repository: pandas-dev/pandas

Issue:
to_html fails for MultiIndexes with empty strings and display.multi_sparse == False
Piggybacking off of #3547.

``` python
import pandas as pd
from nose.tools import assert_raises
pd.set_option('display.multi_sparse', False)
df = pd.DataFrame({'c1': ['a', 'b'], 'c2': ['a', ''], 'data': [1, 2]}).set_index(['c1', 'c2'])
assert_raises(TypeError, df.to_html)  # True
```



Discussion:

Resolving patch:
diff --git a/pandas/core/format.py b/pandas/core/format.py
--- a/pandas/core/format.py
+++ b/pandas/core/format.py
@@ -736,7 +736,7 @@ def _write_hierarchical_rows(self, fmt_values, indent):
                 row.extend(idx_values[i])
                 row.extend(fmt_values[j][i] for j in range(ncols))
                 self.write_tr(row, indent, self.indent_delta, tags=None,
-                              nindex_levels=len(frame.index.nlevels))
+                              nindex_levels=frame.index.nlevels)
 
 
 def _get_level_lengths(levels):


Test patch:
diff --git a/pandas/tests/test_format.py b/pandas/tests/test_format.py
--- a/pandas/tests/test_format.py
+++ b/pandas/tests/test_format.py
@@ -435,6 +435,114 @@ def test_to_html_escape_disabled(self):
 </table>"""
         self.assertEqual(xp, rs)
 
+    def test_to_html_multiindex_sparsify_false_multi_sparse(self):
+        with option_context('display.multi_sparse', False):
+            index = pd.MultiIndex.from_arrays([[0, 0, 1, 1], [0, 1, 0, 1]],
+                                              names=['foo', None])
+
+            df = DataFrame([[0, 1], [2, 3], [4, 5], [6, 7]], index=index)
+
+            result = df.to_html()
+            expected = """\
+<table border="1" class="dataframe">
+  <thead>
+    <tr style="text-align: right;">
+      <th></th>
+      <th></th>
+      <th>0</th>
+      <th>1</th>
+    </tr>
+    <tr>
+      <th>foo</th>
+      <th></th>
+      <th></th>
+      <th></th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <th>0</th>
+      <th>0</th>
+      <td> 0</td>
+      <td> 1</td>
+    </tr>
+    <tr>
+      <th>0</th>
+      <th>1</th>
+      <td> 2</td>
+      <td> 3</td>
+    </tr>
+    <tr>
+      <th>1</th>
+      <th>0</th>
+      <td> 4</td>
+      <td> 5</td>
+    </tr>
+    <tr>
+      <th>1</th>
+      <th>1</th>
+      <td> 6</td>
+      <td> 7</td>
+    </tr>
+  </tbody>
+</table>"""
+            self.assertEquals(result, expected)
+
+            df = DataFrame([[0, 1], [2, 3], [4, 5], [6, 7]],
+                           columns=index[::2], index=index)
+
+            result = df.to_html()
+            expected = """\
+<table border="1" class="dataframe">
+  <thead>
+    <tr>
+      <th></th>
+      <th>foo</th>
+      <th>0</th>
+      <th>1</th>
+    </tr>
+    <tr>
+      <th></th>
+      <th></th>
+      <th>0</th>
+      <th>0</th>
+    </tr>
+    <tr>
+      <th>foo</th>
+      <th></th>
+      <th></th>
+      <th></th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <th>0</th>
+      <th>0</th>
+      <td> 0</td>
+      <td> 1</td>
+    </tr>
+    <tr>
+      <th>0</th>
+      <th>1</th>
+      <td> 2</td>
+      <td> 3</td>
+    </tr>
+    <tr>
+      <th>1</th>
+      <th>0</th>
+      <td> 4</td>
+      <td> 5</td>
+    </tr>
+    <tr>
+      <th>1</th>
+      <th>1</th>
+      <td> 6</td>
+      <td> 7</td>
+    </tr>
+  </tbody>
+</table>"""
+            self.assertEquals(result, expected)
+
     def test_to_html_multiindex_sparsify(self):
         index = pd.MultiIndex.from_arrays([[0, 0, 1, 1], [0, 1, 0, 1]],
                                           names=['foo', None])