pythonmatplotlibsaveplt

Saving matplotlib table creates a lot of whitespace


I'm using matplotlib and python 2.7 to create some tables. When I save the tables, the images come out square, even if the table is only 1 - 2 rows, creating a lot of empty space when I add them to an auto-generated PDF later. The an example of how I'm using the code is here...

import matplotlib.pyplot as plt

t_data = ((1,2), (3,4))
table = plt.table(cellText = t_data, colLabels = ('label 1', 'label 2'), loc='center')
plt.axis('off')
plt.grid('off')
plt.savefig('test.png')

This produces an image like this... You can see you can see the white space around it

Weirdly using plt.show() produces the table in the GUI without white space.

I've tried using various forms of tight_layout=True without luck, as well as making the background transparent (it becomes transparent, but is still there).

Any help would be greatly appreciated.


Solution

  • Since tables are created within axes, the final plot size will depend on the size of the axes. So in principle a solution can be to either set the figure size or set the axes size first and let the table adapt to it.

    import matplotlib.pyplot as plt
    
    fig = plt.figure(figsize=(6,1))
    
    t_data = ((1,2), (3,4))
    table = plt.table(cellText = t_data, 
                      colLabels = ('label 1', 'label 2'),
                      rowLabels = ('row 1', 'row 2'),
                      loc='center')
    
    plt.axis('off')
    plt.grid('off')
    
    plt.savefig(__file__+'test2.png', bbox_inches="tight" )
    plt.show()
    

    enter image description here

    Another solution is to let the table be drawn as it is and find out the bounding box of the table before saving. This allows to create an image which is really tight around the table.

    import matplotlib.pyplot as plt
    import matplotlib.transforms
    
    t_data = ((1,2), (3,4))
    table = plt.table(cellText = t_data, 
                      colLabels = ('label 1', 'label 2'),
                      rowLabels = ('row 1', 'row 2'),
                      loc='center')
    
    plt.axis('off')
    plt.grid('off')
    
    #prepare for saving:
    # draw canvas once
    plt.gcf().canvas.draw()
    # get bounding box of table
    points = table.get_window_extent(plt.gcf()._cachedRenderer).get_points()
    # add 10 pixel spacing
    points[0,:] -= 10; points[1,:] += 10
    # get new bounding box in inches
    nbbox = matplotlib.transforms.Bbox.from_extents(points/plt.gcf().dpi)
    # save and clip by new bounding box
    plt.savefig(__file__+'test.png', bbox_inches=nbbox, )
    
    plt.show()
    

    enter image description here