Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
822
venv/Lib/site-packages/matplotlib/table.py
Normal file
822
venv/Lib/site-packages/matplotlib/table.py
Normal file
|
@ -0,0 +1,822 @@
|
|||
# Original code by:
|
||||
# John Gill <jng@europe.renre.com>
|
||||
# Copyright 2004 John Gill and John Hunter
|
||||
#
|
||||
# Subsequent changes:
|
||||
# The Matplotlib development team
|
||||
# Copyright The Matplotlib development team
|
||||
|
||||
"""
|
||||
Tables drawing.
|
||||
|
||||
Use the factory function `~matplotlib.table.table` to create a ready-made
|
||||
table from texts. If you need more control, use the `.Table` class and its
|
||||
methods.
|
||||
|
||||
The table consists of a grid of cells, which are indexed by (row, column).
|
||||
The cell (0, 0) is positioned at the top left.
|
||||
|
||||
Thanks to John Gill for providing the class and table.
|
||||
"""
|
||||
|
||||
from . import artist, cbook, docstring
|
||||
from .artist import Artist, allow_rasterization
|
||||
from .patches import Rectangle
|
||||
from .text import Text
|
||||
from .transforms import Bbox
|
||||
from .path import Path
|
||||
|
||||
|
||||
class Cell(Rectangle):
|
||||
"""
|
||||
A cell is a `.Rectangle` with some associated `.Text`.
|
||||
|
||||
As a user, you'll most likely not creates cells yourself. Instead, you
|
||||
should use either the `~matplotlib.table.table` factory function or
|
||||
`.Table.add_cell`.
|
||||
"""
|
||||
|
||||
PAD = 0.1
|
||||
"""Padding between text and rectangle."""
|
||||
|
||||
_edges = 'BRTL'
|
||||
_edge_aliases = {'open': '',
|
||||
'closed': _edges, # default
|
||||
'horizontal': 'BT',
|
||||
'vertical': 'RL'
|
||||
}
|
||||
|
||||
def __init__(self, xy, width, height,
|
||||
edgecolor='k', facecolor='w',
|
||||
fill=True,
|
||||
text='',
|
||||
loc=None,
|
||||
fontproperties=None,
|
||||
*,
|
||||
visible_edges='closed',
|
||||
):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
xy : 2-tuple
|
||||
The position of the bottom left corner of the cell.
|
||||
width : float
|
||||
The cell width.
|
||||
height : float
|
||||
The cell height.
|
||||
edgecolor : color
|
||||
The color of the cell border.
|
||||
facecolor : color
|
||||
The cell facecolor.
|
||||
fill : bool
|
||||
Whether the cell background is filled.
|
||||
text : str
|
||||
The cell text.
|
||||
loc : {'left', 'center', 'right'}, default: 'right'
|
||||
The alignment of the text within the cell.
|
||||
fontproperties : dict
|
||||
A dict defining the font properties of the text. Supported keys and
|
||||
values are the keyword arguments accepted by `.FontProperties`.
|
||||
visible_edges : str, default: 'closed'
|
||||
The cell edges to be drawn with a line: a substring of 'BRTL'
|
||||
(bottom, right, top, left), or one of 'open' (no edges drawn),
|
||||
'closed' (all edges drawn), 'horizontal' (bottom and top),
|
||||
'vertical' (right and left).
|
||||
"""
|
||||
|
||||
# Call base
|
||||
Rectangle.__init__(self, xy, width=width, height=height, fill=fill,
|
||||
edgecolor=edgecolor, facecolor=facecolor)
|
||||
self.set_clip_on(False)
|
||||
self.visible_edges = visible_edges
|
||||
|
||||
# Create text object
|
||||
if loc is None:
|
||||
loc = 'right'
|
||||
self._loc = loc
|
||||
self._text = Text(x=xy[0], y=xy[1], clip_on=False,
|
||||
text=text, fontproperties=fontproperties,
|
||||
horizontalalignment=loc, verticalalignment='center')
|
||||
|
||||
def set_transform(self, trans):
|
||||
Rectangle.set_transform(self, trans)
|
||||
# the text does not get the transform!
|
||||
self.stale = True
|
||||
|
||||
def set_figure(self, fig):
|
||||
Rectangle.set_figure(self, fig)
|
||||
self._text.set_figure(fig)
|
||||
|
||||
def get_text(self):
|
||||
"""Return the cell `.Text` instance."""
|
||||
return self._text
|
||||
|
||||
def set_fontsize(self, size):
|
||||
"""Set the text fontsize."""
|
||||
self._text.set_fontsize(size)
|
||||
self.stale = True
|
||||
|
||||
def get_fontsize(self):
|
||||
"""Return the cell fontsize."""
|
||||
return self._text.get_fontsize()
|
||||
|
||||
def auto_set_font_size(self, renderer):
|
||||
"""Shrink font size until the text fits into the cell width."""
|
||||
fontsize = self.get_fontsize()
|
||||
required = self.get_required_width(renderer)
|
||||
while fontsize > 1 and required > self.get_width():
|
||||
fontsize -= 1
|
||||
self.set_fontsize(fontsize)
|
||||
required = self.get_required_width(renderer)
|
||||
|
||||
return fontsize
|
||||
|
||||
@allow_rasterization
|
||||
def draw(self, renderer):
|
||||
if not self.get_visible():
|
||||
return
|
||||
# draw the rectangle
|
||||
Rectangle.draw(self, renderer)
|
||||
# position the text
|
||||
self._set_text_position(renderer)
|
||||
self._text.draw(renderer)
|
||||
self.stale = False
|
||||
|
||||
def _set_text_position(self, renderer):
|
||||
"""Set text up so it is drawn in the right place."""
|
||||
bbox = self.get_window_extent(renderer)
|
||||
# center vertically
|
||||
y = bbox.y0 + bbox.height / 2
|
||||
# position horizontally
|
||||
loc = self._text.get_horizontalalignment()
|
||||
if loc == 'center':
|
||||
x = bbox.x0 + bbox.width / 2
|
||||
elif loc == 'left':
|
||||
x = bbox.x0 + bbox.width * self.PAD
|
||||
else: # right.
|
||||
x = bbox.x0 + bbox.width * (1 - self.PAD)
|
||||
self._text.set_position((x, y))
|
||||
|
||||
def get_text_bounds(self, renderer):
|
||||
"""
|
||||
Return the text bounds as *(x, y, width, height)* in table coordinates.
|
||||
"""
|
||||
return (self._text.get_window_extent(renderer)
|
||||
.transformed(self.get_data_transform().inverted())
|
||||
.bounds)
|
||||
|
||||
def get_required_width(self, renderer):
|
||||
"""Return the minimal required width for the cell."""
|
||||
l, b, w, h = self.get_text_bounds(renderer)
|
||||
return w * (1.0 + (2.0 * self.PAD))
|
||||
|
||||
@docstring.dedent_interpd
|
||||
def set_text_props(self, **kwargs):
|
||||
"""
|
||||
Update the text properties.
|
||||
|
||||
Valid keyword arguments are:
|
||||
|
||||
%(Text)s
|
||||
"""
|
||||
self._text.update(kwargs)
|
||||
self.stale = True
|
||||
|
||||
@property
|
||||
def visible_edges(self):
|
||||
"""
|
||||
The cell edges to be drawn with a line.
|
||||
|
||||
Reading this property returns a substring of 'BRTL' (bottom, right,
|
||||
top, left').
|
||||
|
||||
When setting this property, you can use a substring of 'BRTL' or one
|
||||
of {'open', 'closed', 'horizontal', 'vertical'}.
|
||||
"""
|
||||
return self._visible_edges
|
||||
|
||||
@visible_edges.setter
|
||||
def visible_edges(self, value):
|
||||
if value is None:
|
||||
self._visible_edges = self._edges
|
||||
elif value in self._edge_aliases:
|
||||
self._visible_edges = self._edge_aliases[value]
|
||||
else:
|
||||
if any(edge not in self._edges for edge in value):
|
||||
raise ValueError('Invalid edge param {}, must only be one of '
|
||||
'{} or string of {}'.format(
|
||||
value,
|
||||
", ".join(self._edge_aliases),
|
||||
", ".join(self._edges)))
|
||||
self._visible_edges = value
|
||||
self.stale = True
|
||||
|
||||
def get_path(self):
|
||||
"""Return a `.Path` for the `.visible_edges`."""
|
||||
codes = [Path.MOVETO]
|
||||
codes.extend(
|
||||
Path.LINETO if edge in self._visible_edges else Path.MOVETO
|
||||
for edge in self._edges)
|
||||
if Path.MOVETO not in codes[1:]: # All sides are visible
|
||||
codes[-1] = Path.CLOSEPOLY
|
||||
return Path(
|
||||
[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]],
|
||||
codes,
|
||||
readonly=True
|
||||
)
|
||||
|
||||
|
||||
CustomCell = Cell # Backcompat. alias.
|
||||
|
||||
|
||||
class Table(Artist):
|
||||
"""
|
||||
A table of cells.
|
||||
|
||||
The table consists of a grid of cells, which are indexed by (row, column).
|
||||
|
||||
For a simple table, you'll have a full grid of cells with indices from
|
||||
(0, 0) to (num_rows-1, num_cols-1), in which the cell (0, 0) is positioned
|
||||
at the top left. However, you can also add cells with negative indices.
|
||||
You don't have to add a cell to every grid position, so you can create
|
||||
tables that have holes.
|
||||
|
||||
*Note*: You'll usually not create an empty table from scratch. Instead use
|
||||
`~matplotlib.table.table` to create a table from data.
|
||||
"""
|
||||
codes = {'best': 0,
|
||||
'upper right': 1, # default
|
||||
'upper left': 2,
|
||||
'lower left': 3,
|
||||
'lower right': 4,
|
||||
'center left': 5,
|
||||
'center right': 6,
|
||||
'lower center': 7,
|
||||
'upper center': 8,
|
||||
'center': 9,
|
||||
'top right': 10,
|
||||
'top left': 11,
|
||||
'bottom left': 12,
|
||||
'bottom right': 13,
|
||||
'right': 14,
|
||||
'left': 15,
|
||||
'top': 16,
|
||||
'bottom': 17,
|
||||
}
|
||||
"""Possible values where to place the table relative to the Axes."""
|
||||
|
||||
FONTSIZE = 10
|
||||
|
||||
AXESPAD = 0.02
|
||||
"""The border between the Axes and the table edge in Axes units."""
|
||||
|
||||
def __init__(self, ax, loc=None, bbox=None, **kwargs):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
ax : `matplotlib.axes.Axes`
|
||||
The `~.axes.Axes` to plot the table into.
|
||||
loc : str
|
||||
The position of the cell with respect to *ax*. This must be one of
|
||||
the `~.Table.codes`.
|
||||
bbox : `.Bbox` or None
|
||||
A bounding box to draw the table into. If this is not *None*, this
|
||||
overrides *loc*.
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
**kwargs
|
||||
`.Artist` properties.
|
||||
"""
|
||||
|
||||
Artist.__init__(self)
|
||||
|
||||
if isinstance(loc, str):
|
||||
if loc not in self.codes:
|
||||
raise ValueError(
|
||||
"Unrecognized location {!r}. Valid locations are\n\t{}"
|
||||
.format(loc, '\n\t'.join(self.codes)))
|
||||
loc = self.codes[loc]
|
||||
self.set_figure(ax.figure)
|
||||
self._axes = ax
|
||||
self._loc = loc
|
||||
self._bbox = bbox
|
||||
|
||||
# use axes coords
|
||||
ax._unstale_viewLim()
|
||||
self.set_transform(ax.transAxes)
|
||||
|
||||
self._cells = {}
|
||||
self._edges = None
|
||||
self._autoColumns = []
|
||||
self._autoFontsize = True
|
||||
self.update(kwargs)
|
||||
|
||||
self.set_clip_on(False)
|
||||
|
||||
def add_cell(self, row, col, *args, **kwargs):
|
||||
"""
|
||||
Create a cell and add it to the table.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
row : int
|
||||
Row index.
|
||||
col : int
|
||||
Column index.
|
||||
*args, **kwargs
|
||||
All other parameters are passed on to `Cell`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
`.Cell`
|
||||
The created cell.
|
||||
|
||||
"""
|
||||
xy = (0, 0)
|
||||
cell = Cell(xy, visible_edges=self.edges, *args, **kwargs)
|
||||
self[row, col] = cell
|
||||
return cell
|
||||
|
||||
def __setitem__(self, position, cell):
|
||||
"""
|
||||
Set a custom cell in a given position.
|
||||
"""
|
||||
cbook._check_isinstance(Cell, cell=cell)
|
||||
try:
|
||||
row, col = position[0], position[1]
|
||||
except Exception as err:
|
||||
raise KeyError('Only tuples length 2 are accepted as '
|
||||
'coordinates') from err
|
||||
cell.set_figure(self.figure)
|
||||
cell.set_transform(self.get_transform())
|
||||
cell.set_clip_on(False)
|
||||
self._cells[row, col] = cell
|
||||
self.stale = True
|
||||
|
||||
def __getitem__(self, position):
|
||||
"""Retrieve a custom cell from a given position."""
|
||||
return self._cells[position]
|
||||
|
||||
@property
|
||||
def edges(self):
|
||||
"""
|
||||
The default value of `~.Cell.visible_edges` for newly added
|
||||
cells using `.add_cell`.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This setting does currently only affect newly created cells using
|
||||
`.add_cell`.
|
||||
|
||||
To change existing cells, you have to set their edges explicitly::
|
||||
|
||||
for c in tab.get_celld().values():
|
||||
c.visible_edges = 'horizontal'
|
||||
|
||||
"""
|
||||
return self._edges
|
||||
|
||||
@edges.setter
|
||||
def edges(self, value):
|
||||
self._edges = value
|
||||
self.stale = True
|
||||
|
||||
def _approx_text_height(self):
|
||||
return (self.FONTSIZE / 72.0 * self.figure.dpi /
|
||||
self._axes.bbox.height * 1.2)
|
||||
|
||||
@allow_rasterization
|
||||
def draw(self, renderer):
|
||||
# docstring inherited
|
||||
|
||||
# Need a renderer to do hit tests on mouseevent; assume the last one
|
||||
# will do
|
||||
if renderer is None:
|
||||
renderer = self.figure._cachedRenderer
|
||||
if renderer is None:
|
||||
raise RuntimeError('No renderer defined')
|
||||
|
||||
if not self.get_visible():
|
||||
return
|
||||
renderer.open_group('table', gid=self.get_gid())
|
||||
self._update_positions(renderer)
|
||||
|
||||
for key in sorted(self._cells):
|
||||
self._cells[key].draw(renderer)
|
||||
|
||||
renderer.close_group('table')
|
||||
self.stale = False
|
||||
|
||||
def _get_grid_bbox(self, renderer):
|
||||
"""
|
||||
Get a bbox, in axes coordinates for the cells.
|
||||
|
||||
Only include those in the range (0, 0) to (maxRow, maxCol).
|
||||
"""
|
||||
boxes = [cell.get_window_extent(renderer)
|
||||
for (row, col), cell in self._cells.items()
|
||||
if row >= 0 and col >= 0]
|
||||
bbox = Bbox.union(boxes)
|
||||
return bbox.transformed(self.get_transform().inverted())
|
||||
|
||||
def contains(self, mouseevent):
|
||||
# docstring inherited
|
||||
inside, info = self._default_contains(mouseevent)
|
||||
if inside is not None:
|
||||
return inside, info
|
||||
# TODO: Return index of the cell containing the cursor so that the user
|
||||
# doesn't have to bind to each one individually.
|
||||
renderer = self.figure._cachedRenderer
|
||||
if renderer is not None:
|
||||
boxes = [cell.get_window_extent(renderer)
|
||||
for (row, col), cell in self._cells.items()
|
||||
if row >= 0 and col >= 0]
|
||||
bbox = Bbox.union(boxes)
|
||||
return bbox.contains(mouseevent.x, mouseevent.y), {}
|
||||
else:
|
||||
return False, {}
|
||||
|
||||
def get_children(self):
|
||||
"""Return the Artists contained by the table."""
|
||||
return list(self._cells.values())
|
||||
|
||||
def get_window_extent(self, renderer):
|
||||
"""Return the bounding box of the table in window coords."""
|
||||
self._update_positions(renderer)
|
||||
boxes = [cell.get_window_extent(renderer)
|
||||
for cell in self._cells.values()]
|
||||
return Bbox.union(boxes)
|
||||
|
||||
def _do_cell_alignment(self):
|
||||
"""
|
||||
Calculate row heights and column widths; position cells accordingly.
|
||||
"""
|
||||
# Calculate row/column widths
|
||||
widths = {}
|
||||
heights = {}
|
||||
for (row, col), cell in self._cells.items():
|
||||
height = heights.setdefault(row, 0.0)
|
||||
heights[row] = max(height, cell.get_height())
|
||||
width = widths.setdefault(col, 0.0)
|
||||
widths[col] = max(width, cell.get_width())
|
||||
|
||||
# work out left position for each column
|
||||
xpos = 0
|
||||
lefts = {}
|
||||
for col in sorted(widths):
|
||||
lefts[col] = xpos
|
||||
xpos += widths[col]
|
||||
|
||||
ypos = 0
|
||||
bottoms = {}
|
||||
for row in sorted(heights, reverse=True):
|
||||
bottoms[row] = ypos
|
||||
ypos += heights[row]
|
||||
|
||||
# set cell positions
|
||||
for (row, col), cell in self._cells.items():
|
||||
cell.set_x(lefts[col])
|
||||
cell.set_y(bottoms[row])
|
||||
|
||||
def auto_set_column_width(self, col):
|
||||
"""
|
||||
Automatically set the widths of given columns to optimal sizes.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
col : int or sequence of ints
|
||||
The indices of the columns to auto-scale.
|
||||
"""
|
||||
# check for col possibility on iteration
|
||||
try:
|
||||
iter(col)
|
||||
except (TypeError, AttributeError):
|
||||
self._autoColumns.append(col)
|
||||
else:
|
||||
for cell in col:
|
||||
self._autoColumns.append(cell)
|
||||
|
||||
self.stale = True
|
||||
|
||||
def _auto_set_column_width(self, col, renderer):
|
||||
"""Automatically set width for column."""
|
||||
cells = [cell for key, cell in self._cells.items() if key[1] == col]
|
||||
max_width = max((cell.get_required_width(renderer) for cell in cells),
|
||||
default=0)
|
||||
for cell in cells:
|
||||
cell.set_width(max_width)
|
||||
|
||||
def auto_set_font_size(self, value=True):
|
||||
"""Automatically set font size."""
|
||||
self._autoFontsize = value
|
||||
self.stale = True
|
||||
|
||||
def _auto_set_font_size(self, renderer):
|
||||
|
||||
if len(self._cells) == 0:
|
||||
return
|
||||
fontsize = next(iter(self._cells.values())).get_fontsize()
|
||||
cells = []
|
||||
for key, cell in self._cells.items():
|
||||
# ignore auto-sized columns
|
||||
if key[1] in self._autoColumns:
|
||||
continue
|
||||
size = cell.auto_set_font_size(renderer)
|
||||
fontsize = min(fontsize, size)
|
||||
cells.append(cell)
|
||||
|
||||
# now set all fontsizes equal
|
||||
for cell in self._cells.values():
|
||||
cell.set_fontsize(fontsize)
|
||||
|
||||
def scale(self, xscale, yscale):
|
||||
"""Scale column widths by *xscale* and row heights by *yscale*."""
|
||||
for c in self._cells.values():
|
||||
c.set_width(c.get_width() * xscale)
|
||||
c.set_height(c.get_height() * yscale)
|
||||
|
||||
def set_fontsize(self, size):
|
||||
"""
|
||||
Set the font size, in points, of the cell text.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
size : float
|
||||
|
||||
Notes
|
||||
-----
|
||||
As long as auto font size has not been disabled, the value will be
|
||||
clipped such that the text fits horizontally into the cell.
|
||||
|
||||
You can disable this behavior using `.auto_set_font_size`.
|
||||
|
||||
>>> the_table.auto_set_font_size(False)
|
||||
>>> the_table.set_fontsize(20)
|
||||
|
||||
However, there is no automatic scaling of the row height so that the
|
||||
text may exceed the cell boundary.
|
||||
"""
|
||||
for cell in self._cells.values():
|
||||
cell.set_fontsize(size)
|
||||
self.stale = True
|
||||
|
||||
def _offset(self, ox, oy):
|
||||
"""Move all the artists by ox, oy (axes coords)."""
|
||||
for c in self._cells.values():
|
||||
x, y = c.get_x(), c.get_y()
|
||||
c.set_x(x + ox)
|
||||
c.set_y(y + oy)
|
||||
|
||||
def _update_positions(self, renderer):
|
||||
# called from renderer to allow more precise estimates of
|
||||
# widths and heights with get_window_extent
|
||||
|
||||
# Do any auto width setting
|
||||
for col in self._autoColumns:
|
||||
self._auto_set_column_width(col, renderer)
|
||||
|
||||
if self._autoFontsize:
|
||||
self._auto_set_font_size(renderer)
|
||||
|
||||
# Align all the cells
|
||||
self._do_cell_alignment()
|
||||
|
||||
bbox = self._get_grid_bbox(renderer)
|
||||
l, b, w, h = bbox.bounds
|
||||
|
||||
if self._bbox is not None:
|
||||
# Position according to bbox
|
||||
rl, rb, rw, rh = self._bbox
|
||||
self.scale(rw / w, rh / h)
|
||||
ox = rl - l
|
||||
oy = rb - b
|
||||
self._do_cell_alignment()
|
||||
else:
|
||||
# Position using loc
|
||||
(BEST, UR, UL, LL, LR, CL, CR, LC, UC, C,
|
||||
TR, TL, BL, BR, R, L, T, B) = range(len(self.codes))
|
||||
# defaults for center
|
||||
ox = (0.5 - w / 2) - l
|
||||
oy = (0.5 - h / 2) - b
|
||||
if self._loc in (UL, LL, CL): # left
|
||||
ox = self.AXESPAD - l
|
||||
if self._loc in (BEST, UR, LR, R, CR): # right
|
||||
ox = 1 - (l + w + self.AXESPAD)
|
||||
if self._loc in (BEST, UR, UL, UC): # upper
|
||||
oy = 1 - (b + h + self.AXESPAD)
|
||||
if self._loc in (LL, LR, LC): # lower
|
||||
oy = self.AXESPAD - b
|
||||
if self._loc in (LC, UC, C): # center x
|
||||
ox = (0.5 - w / 2) - l
|
||||
if self._loc in (CL, CR, C): # center y
|
||||
oy = (0.5 - h / 2) - b
|
||||
|
||||
if self._loc in (TL, BL, L): # out left
|
||||
ox = - (l + w)
|
||||
if self._loc in (TR, BR, R): # out right
|
||||
ox = 1.0 - l
|
||||
if self._loc in (TR, TL, T): # out top
|
||||
oy = 1.0 - b
|
||||
if self._loc in (BL, BR, B): # out bottom
|
||||
oy = - (b + h)
|
||||
|
||||
self._offset(ox, oy)
|
||||
|
||||
def get_celld(self):
|
||||
r"""
|
||||
Return a dict of cells in the table mapping *(row, column)* to
|
||||
`.Cell`\s.
|
||||
|
||||
Notes
|
||||
-----
|
||||
You can also directly index into the Table object to access individual
|
||||
cells::
|
||||
|
||||
cell = table[row, col]
|
||||
|
||||
"""
|
||||
return self._cells
|
||||
|
||||
|
||||
docstring.interpd.update(Table=artist.kwdoc(Table))
|
||||
|
||||
|
||||
@docstring.dedent_interpd
|
||||
def table(ax,
|
||||
cellText=None, cellColours=None,
|
||||
cellLoc='right', colWidths=None,
|
||||
rowLabels=None, rowColours=None, rowLoc='left',
|
||||
colLabels=None, colColours=None, colLoc='center',
|
||||
loc='bottom', bbox=None, edges='closed',
|
||||
**kwargs):
|
||||
"""
|
||||
Add a table to an `~.axes.Axes`.
|
||||
|
||||
At least one of *cellText* or *cellColours* must be specified. These
|
||||
parameters must be 2D lists, in which the outer lists define the rows and
|
||||
the inner list define the column values per row. Each row must have the
|
||||
same number of elements.
|
||||
|
||||
The table can optionally have row and column headers, which are configured
|
||||
using *rowLabels*, *rowColours*, *rowLoc* and *colLabels*, *colColours*,
|
||||
*colLoc* respectively.
|
||||
|
||||
For finer grained control over tables, use the `.Table` class and add it to
|
||||
the axes with `.Axes.add_table`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
cellText : 2D list of str, optional
|
||||
The texts to place into the table cells.
|
||||
|
||||
*Note*: Line breaks in the strings are currently not accounted for and
|
||||
will result in the text exceeding the cell boundaries.
|
||||
|
||||
cellColours : 2D list of colors, optional
|
||||
The background colors of the cells.
|
||||
|
||||
cellLoc : {'left', 'center', 'right'}, default: 'right'
|
||||
The alignment of the text within the cells.
|
||||
|
||||
colWidths : list of float, optional
|
||||
The column widths in units of the axes. If not given, all columns will
|
||||
have a width of *1 / ncols*.
|
||||
|
||||
rowLabels : list of str, optional
|
||||
The text of the row header cells.
|
||||
|
||||
rowColours : list of colors, optional
|
||||
The colors of the row header cells.
|
||||
|
||||
rowLoc : {'left', 'center', 'right'}, default: 'left'
|
||||
The text alignment of the row header cells.
|
||||
|
||||
colLabels : list of str, optional
|
||||
The text of the column header cells.
|
||||
|
||||
colColours : list of colors, optional
|
||||
The colors of the column header cells.
|
||||
|
||||
colLoc : {'left', 'center', 'right'}, default: 'left'
|
||||
The text alignment of the column header cells.
|
||||
|
||||
loc : str, optional
|
||||
The position of the cell with respect to *ax*. This must be one of
|
||||
the `~.Table.codes`.
|
||||
|
||||
bbox : `.Bbox`, optional
|
||||
A bounding box to draw the table into. If this is not *None*, this
|
||||
overrides *loc*.
|
||||
|
||||
edges : substring of 'BRTL' or {'open', 'closed', 'horizontal', 'vertical'}
|
||||
The cell edges to be drawn with a line. See also
|
||||
`~.Cell.visible_edges`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
`~matplotlib.table.Table`
|
||||
The created table.
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
**kwargs
|
||||
`.Table` properties.
|
||||
|
||||
%(Table)s
|
||||
"""
|
||||
|
||||
if cellColours is None and cellText is None:
|
||||
raise ValueError('At least one argument from "cellColours" or '
|
||||
'"cellText" must be provided to create a table.')
|
||||
|
||||
# Check we have some cellText
|
||||
if cellText is None:
|
||||
# assume just colours are needed
|
||||
rows = len(cellColours)
|
||||
cols = len(cellColours[0])
|
||||
cellText = [[''] * cols] * rows
|
||||
|
||||
rows = len(cellText)
|
||||
cols = len(cellText[0])
|
||||
for row in cellText:
|
||||
if len(row) != cols:
|
||||
raise ValueError("Each row in 'cellText' must have {} columns"
|
||||
.format(cols))
|
||||
|
||||
if cellColours is not None:
|
||||
if len(cellColours) != rows:
|
||||
raise ValueError("'cellColours' must have {} rows".format(rows))
|
||||
for row in cellColours:
|
||||
if len(row) != cols:
|
||||
raise ValueError("Each row in 'cellColours' must have {} "
|
||||
"columns".format(cols))
|
||||
else:
|
||||
cellColours = ['w' * cols] * rows
|
||||
|
||||
# Set colwidths if not given
|
||||
if colWidths is None:
|
||||
colWidths = [1.0 / cols] * cols
|
||||
|
||||
# Fill in missing information for column
|
||||
# and row labels
|
||||
rowLabelWidth = 0
|
||||
if rowLabels is None:
|
||||
if rowColours is not None:
|
||||
rowLabels = [''] * rows
|
||||
rowLabelWidth = colWidths[0]
|
||||
elif rowColours is None:
|
||||
rowColours = 'w' * rows
|
||||
|
||||
if rowLabels is not None:
|
||||
if len(rowLabels) != rows:
|
||||
raise ValueError("'rowLabels' must be of length {0}".format(rows))
|
||||
|
||||
# If we have column labels, need to shift
|
||||
# the text and colour arrays down 1 row
|
||||
offset = 1
|
||||
if colLabels is None:
|
||||
if colColours is not None:
|
||||
colLabels = [''] * cols
|
||||
else:
|
||||
offset = 0
|
||||
elif colColours is None:
|
||||
colColours = 'w' * cols
|
||||
|
||||
# Set up cell colours if not given
|
||||
if cellColours is None:
|
||||
cellColours = ['w' * cols] * rows
|
||||
|
||||
# Now create the table
|
||||
table = Table(ax, loc, bbox, **kwargs)
|
||||
table.edges = edges
|
||||
height = table._approx_text_height()
|
||||
|
||||
# Add the cells
|
||||
for row in range(rows):
|
||||
for col in range(cols):
|
||||
table.add_cell(row + offset, col,
|
||||
width=colWidths[col], height=height,
|
||||
text=cellText[row][col],
|
||||
facecolor=cellColours[row][col],
|
||||
loc=cellLoc)
|
||||
# Do column labels
|
||||
if colLabels is not None:
|
||||
for col in range(cols):
|
||||
table.add_cell(0, col,
|
||||
width=colWidths[col], height=height,
|
||||
text=colLabels[col], facecolor=colColours[col],
|
||||
loc=colLoc)
|
||||
|
||||
# Do row labels
|
||||
if rowLabels is not None:
|
||||
for row in range(rows):
|
||||
table.add_cell(row + offset, -1,
|
||||
width=rowLabelWidth or 1e-15, height=height,
|
||||
text=rowLabels[row], facecolor=rowColours[row],
|
||||
loc=rowLoc)
|
||||
if rowLabelWidth == 0:
|
||||
table.auto_set_column_width(-1)
|
||||
|
||||
ax.add_table(table)
|
||||
return table
|
Loading…
Add table
Add a link
Reference in a new issue