diff --git a/doc/source/whatsnew/v0.16.1.txt b/doc/source/whatsnew/v0.16.1.txt index ffc08fa4ff169..090ef9ea92fc1 100644 --- a/doc/source/whatsnew/v0.16.1.txt +++ b/doc/source/whatsnew/v0.16.1.txt @@ -157,3 +157,5 @@ Bug Fixes - Bug where dividing a dataframe containing values of type ``Decimal`` by another ``Decimal`` would raise. (:issue:`9787`) - Bug where using DataFrames asfreq would remove the name of the index. (:issue:`9885`) - Changed caching in ``AbstractHolidayCalendar`` to be at the instance level rather than at the class level as the latter can result in unexpected behaviour. (:issue:`9552`) + +- Fixed latex output for multi-indexed dataframes (:issue:`9778`) diff --git a/pandas/core/format.py b/pandas/core/format.py index 7b8a3161b5e05..06e1fab27cd6d 100644 --- a/pandas/core/format.py +++ b/pandas/core/format.py @@ -613,8 +613,12 @@ def get_col_type(dtype): name = any(self.frame.columns.names) for i, lev in enumerate(self.frame.index.levels): lev2 = lev.format(name=name) - width = len(lev2[0]) - lev3 = [' ' * width] * clevels + lev2 + blank = ' ' * len(lev2[0]) + lev3 = [blank] * clevels + for level_idx, group in itertools.groupby( + self.frame.index.labels[i]): + count = len(list(group)) + lev3.extend([lev2[level_idx]] + [blank] * (count - 1)) strcols.insert(i, lev3) if column_format is None: diff --git a/pandas/tests/test_format.py b/pandas/tests/test_format.py index 1dcdbf12a6b59..e3455d2449b55 100644 --- a/pandas/tests/test_format.py +++ b/pandas/tests/test_format.py @@ -2194,6 +2194,28 @@ def test_to_latex_multiindex(self): x & y & a \\ \bottomrule \end{tabular} +""" + self.assertEqual(result, expected) + + df = DataFrame.from_dict({ + ('c1', 0): pd.Series(dict((x, x) for x in range(4))), + ('c1', 1): pd.Series(dict((x, x + 4) for x in range(4))), + ('c2', 0): pd.Series(dict((x, x) for x in range(4))), + ('c2', 1): pd.Series(dict((x, x + 4) for x in range(4))), + ('c3', 0): pd.Series(dict((x, x) for x in range(4))), + }).T + result = df.to_latex() + expected = r"""\begin{tabular}{llrrrr} +\toprule + & & 0 & 1 & 2 & 3 \\ +\midrule +c1 & 0 & 0 & 1 & 2 & 3 \\ + & 1 & 4 & 5 & 6 & 7 \\ +c2 & 0 & 0 & 1 & 2 & 3 \\ + & 1 & 4 & 5 & 6 & 7 \\ +c3 & 0 & 0 & 1 & 2 & 3 \\ +\bottomrule +\end{tabular} """ self.assertEqual(result, expected)