14

I need to create a table using matplotlib from a list of dictionaries.

For this I use the following function, which I found in another answer on this site:

import matplotlib.pyplot as plt
from matplotlib.externals import six
import matplotlib
matplotlib.rc('font', family='Arial')

def render_mpl_table(data, col_width=3.0, row_height=2, font_size=10,
                     header_color='#40466e', row_colors=['#f1f1f2', 'w'], edge_color='w',
                     bbox=[0, 0, 1, 1], header_columns=0,
                     ax=None, **kwargs):
    if ax is None:
        size = (np.array(data.shape[::-1]) + np.array([0, 1])) * np.array([col_width, row_height])
        fig, ax = plt.subplots(figsize=size)
        ax.axis('off')

    mpl_table = ax.table(cellText=data.values, bbox=bbox, colLabels=data.columns, **kwargs)

    mpl_table.auto_set_font_size(False)
    mpl_table.set_fontsize(font_size)

    for k, cell in six.iteritems(mpl_table._cells):
        cell.set_edgecolor(edge_color)
        if k[0] == 0 or k[1] < header_columns:
            cell.set_text_props(weight='bold', color='w', wrap=True)
            cell.set_facecolor(header_color)
        else:
            cell.set_facecolor(row_colors[k[0]%len(row_colors) ])
    return ax

The problem is that I cannot wrap the text inside a cell, even though I put the properties at cell.set_text_props(weight='bold', color='w', wrap=True).

Example image:enter image description here

Thanks for any help!

Litwos
  • 1,278
  • 4
  • 19
  • 44
  • `wrap=True` wraps the text at the figure edges. It won't help here. I'm not aware of an automatic solution, but [this question](http://stackoverflow.com/questions/4018860/text-box-with-line-wrapping-in-matplotlib?rq=1) may help you to build one yourself. – ImportanceOfBeingErnest Apr 07 '17 at 16:48
  • @ImportanceOfBeingErnest Thanks for the tip. I will check it out. – Litwos Apr 08 '17 at 16:45
  • is that worked for you? I am also facing same issue. please share the solution you picked, even alternative table solution instead of matplotlib but with table wrap. Thanks in advance! :) – Hara Mar 11 '19 at 11:16
  • 1
    Hello, @Haranadh: I ended up using Reportlab. It is much better for generating tables. Check it out here: https://www.reportlab.com/opensource Cheers :) – Litwos Mar 12 '19 at 09:33

2 Answers2

3

If you want to apply an automatical wrap, an additional option might be the useage of textwrap at your table content outside the tables definition.

import matplotlib.pyplot as plt
import textwrap as twp
import numpy as np

#create column headers with long text and apply textwrap with \n after defined lenght
columns=[twp.fill('this is a long column header text',25), twp.fill('...and this is an even longer column header text',25)]
#create rows
rows=[1,2]
#create (stupid) content
cell_text=[[100,200],[100,200]]

#create figure with simple data (just for demo)
fig,ax=plt.subplots(1,1)
x=np.arange(100)
ax.plot(x,np.sin(x/10))
# insert table with wrapped column headers and data
table=ax.table(cellText=cell_text,
                  rowLabels=rows,
                  colLabels=columns,
                  loc='bottom',
                  bbox=[0.0,-0.3,1,.2])

#adjust format of table and plot
table.auto_set_font_size(False)
table.set_fontsize(9)
plt.subplots_adjust(left=0.2, bottom=0.1)
plt.tight_layout()

example of table with text wrap

Aroc
  • 1,022
  • 1
  • 10
  • 18
2

The easiest way to do this is to just use '\n' in your text and then play with column width and row height. It is not a built in feature.