Stan
Stan

Reputation: 81

Matplotlib table with double headers

Hi is possible to make a matplotlib table to have a "double header" like this (mind the dashed line)

          ----------------------------------------
          |  Feb Total     |     YTD Total        |
          ----------------------------------------
          |  2014|2015     | 2014/2015| 2015/2016 |
--------------------------------------------------
|VVI-ID   | 12  | 20       | 188      | 169       |
--------------------------------------------------
|TDI-ID   | 34  | 45       | 556      | 456       |

Upvotes: 2

Views: 9545

Answers (1)

Vadim Shkaberda
Vadim Shkaberda

Reputation: 2936

You can do this by using another tables with no data as headers. That is, you create empty tables, whose column labels will be the headers for your table. Let's consider this demo example. At first, add tables header_0 and header_1. At second, correct headers' and table's argument bbox to position all tables correctly. Since the tables are overlapped, the table with data should be the last one.

import numpy as np
import matplotlib.pyplot as plt


data = [[  66386,  174296,   75131,  577908,   32015],
        [  58230,  381139,   78045,   99308,  160454],
        [  89135,   80552,  152558,  497981,  603535],
        [  78415,   81858,  150656,  193263,   69638],
        [ 139361,  331509,  343164,  781380,   52269]]

columns = ('Freeze', 'Wind', 'Flood', 'Quake', 'Hail')
rows = ['%d year' % x for x in (100, 50, 20, 10, 5)]

values = np.arange(0, 2500, 500)
value_increment = 1000

# Get some pastel shades for the colors
colors = plt.cm.BuPu(np.linspace(0, 0.5, len(rows)))
n_rows = len(data)

index = np.arange(len(columns)) + 0.3
bar_width = 0.4

# Initialize the vertical-offset for the stacked bar chart.
y_offset = np.array([0.0] * len(columns))

# Plot bars and create text labels for the table
cell_text = []
for row in range(n_rows):
    plt.bar(index, data[row], bar_width, bottom=y_offset, color=colors[row])
    y_offset = y_offset + data[row]
    cell_text.append(['%1.1f' % (x/1000.0) for x in y_offset])
# Reverse colors and text labels to display the last value at the top.
colors = colors[::-1]
cell_text.reverse()

# Add headers and a table at the bottom of the axes
header_0 = plt.table(cellText=[['']*2],
                     colLabels=['Extra header 1', 'Extra header 2'],
                     loc='bottom',
                     bbox=[0, -0.1, 0.8, 0.1]
                     )

header_1 = plt.table(cellText=[['']],
                     colLabels=['Just Hail'],
                     loc='bottom',
                     bbox=[0.8, -0.1, 0.2, 0.1]
                     )

the_table = plt.table(cellText=cell_text,
                      rowLabels=rows,
                      rowColours=colors,
                      colLabels=columns,
                      loc='bottom',
                      bbox=[0, -0.35, 1.0, 0.3]
                      )

# Adjust layout to make room for the table:
plt.subplots_adjust(left=0.2, bottom=-0.2)

plt.ylabel("Loss in ${0}'s".format(value_increment))
plt.yticks(values * value_increment, ['%d' % val for val in values])
plt.xticks([])
plt.title('Loss by Disaster')

plt.show()

enter image description here

If extra header is symmetric or combine equal quantity of "normal" header, all you need to do is to add an extra header table and correct bbox of data table like this (the same example with deleted column):

header = plt.table(cellText=[['']*2],
                      colLabels=['Extra header 1', 'Extra header 2'],
                      loc='bottom'
                      )

the_table = plt.table(cellText=cell_text,
                      rowLabels=rows,
                      rowColours=colors,
                      colLabels=columns,
                      loc='bottom',
                      bbox=[0, -0.35, 1.0, 0.3]
                      )

enter image description here

Upvotes: 6

Related Questions