3

How can one print a multi-index Dataframe such as the one below:

import numpy as np
import tabulate
import pandas as pd


df = pd.DataFrame(np.random.randn(4, 3),
                  index=pd.MultiIndex.from_product([["foo", "bar"],
                                                    ["one", "two"]]),
                  columns=list("ABC"))

so that the two levels of the Multindex show as separate columns, much the same way pandas itself prints it:

In [16]: df
Out[16]: 
                A         B         C
foo one -0.040337  0.653915 -0.359834
    two  0.271542  1.328517  1.704389
bar one -1.246009  0.087229  0.039282
    two -1.217514  0.721025 -0.017185

However, tabulate prints like this:

In [28]: print(tabulate.tabulate(df, tablefmt="github", headers="keys", showindex="always"))
|                |          A |         B |          C |
|----------------|------------|-----------|------------|
| ('foo', 'one') | -0.0403371 | 0.653915  | -0.359834  |
| ('foo', 'two') |  0.271542  | 1.32852   |  1.70439   |
| ('bar', 'one') | -1.24601   | 0.0872285 |  0.039282  |
| ('bar', 'two') | -1.21751   | 0.721025  | -0.0171852 |
sluque
  • 495
  • 4
  • 12

1 Answers1

2

MultiIndexes are represented by tuples internally, so tabulate is showing you the right thing.

If you want column-like display, the easiest is to reset_index first:

print(tabulate.tabulate(df.reset_index().rename(columns={'level_0':'', 'level_1': ''}), tablefmt="github", headers="keys", showindex=False))

Output:

|     |     |         A |         B |         C |
|-----|-----|-----------|-----------|-----------|
| foo | one | -0.108977 |  2.03593  |  1.11258  |
| foo | two |  0.65117  | -1.48314  |  0.391379 |
| bar | one | -0.660148 |  1.34875  | -1.10848  |
| bar | two |  0.561418 |  0.762137 |  0.723432 |

Alternatively, you can rework the MultiIndex to a single index:

df2 = df.copy()
df2.index = df.index.map(lambda x: '|'.join(f'{e:>5} ' for e in x))

print(tabulate.tabulate(df2.rename_axis('index'), tablefmt="github", headers="keys", showindex="always"))

Output:

| index      |         A |         B |         C |
|------------|-----------|-----------|-----------|
| foo |  one | -0.108977 |  2.03593  |  1.11258  |
| foo |  two |  0.65117  | -1.48314  |  0.391379 |
| bar |  one | -0.660148 |  1.34875  | -1.10848  |
| bar |  two |  0.561418 |  0.762137 |  0.723432 |
mozway
  • 194,879
  • 13
  • 39
  • 75
  • 1
    Yes, the first representation you show seems to be the closest this will get. I can find a way to remove the redundant rows in the reset index to match the pandas display. I really like pandas concise display, which makes it ideal for presentation. – sluque Nov 18 '21 at 13:39