使用 matplotlib 沿图表绘制表格 [英] Plot table along chart using matplotlib

查看:67
本文介绍了使用 matplotlib 沿图表绘制表格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我有这段代码:

将pandas导入为pd导入 matplotlib.pyplot 作为 plt将 matplotlib 导入为 mpl将 numpy 导入为 np从 matplotlib.font_manager 导入 FontProperties数据 = np.random.uniform(0, 1, 80).reshape(20, 4)final_data = [['%.3f' % j for j in i] for i in data]mpl.style.use('seaborn')mpl.rc('xtick', labelsize = 7)mpl.rc('ytick', labelsize = 7)fig = plt.figure()fig.subplots_adjust(left=0.1, wspace=0.1)plt.subplot2grid((1, 4), (0, 0), colspan=3)table_subplot = plt.subplot2grid((1, 4), (0, 3))table = plt.table(cellText=final_data, colLabels=['A', 'B', 'C', 'D'], loc='center', cellLoc='center', colLabels=['#FFFFFF','#F3CC32'、'#2769BD'、'#DC3735'])table.auto_set_font_size(False)table.set_fontsize(7)table.auto_set_column_width((-1, 0, 1, 2, 3))for (row, col), table.get_celld().items() 中的单元格:如果(行== 0):cell.set_text_props(fontproperties=FontProperties(weight='bold', size=7))plt.axis('关闭')plt.show()

将其作为输出生成:

我知道情节是空的,但我打算在那里添加一些数据,所以我需要记住这一点!我想在表格中再添加一行以有一个标题.这一行应该只在最后三列上,就像这样:

 +-----------------+|标题 |+-----+-----+|一个 |乙 |C |D |+-----+-----+-----+-----+|... |... |... |... |+-----+-----+-----+-----+|... |... |... |... |+-----+-----+-----+-----+

标题行的宽度应与 A、B 和 C 列的宽度总和相匹配.我一直在玩,但我无法得到它......有人可以帮助我吗?

谢谢!

解决方案

Matplotlib 表没有colspan"或rowspan"的概念,其中单元格跨越多列或多行.人们可能会认为一个单元格的宽度可以是其他单元格的三倍.但是,这会引入不必要的转变

您可以选择设置

<小时>

附录

以上不允许为表格单元格的背景着色.为此,可以使用以下解决方法:

将 numpy 导入为 np导入 matplotlib.pyplot 作为 plt导入 matplotlib.table从 matplotlib.collections 导入 LineCollection从 matplotlib.path 导入路径类 MyCell(matplotlib.table.CustomCell):def __init__(self, *args,visible_edges, **kwargs):super().__init__(*args,visible_edges=visible_edges, **kwargs)seg = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0],[0.0, 1.0], [0.0, 0.0]]).reshape(-1, 1, 2)段 = np.concatenate([seg[:-1], seg[1:]],axis=1)self.edgelines = LineCollection(segments, edgecolor=kwargs.get("edgecolor"))self._text.set_zorder(2)self.set_zorder(1)def set_transform(self, trans):self.edgelines.set_transform(trans)super().set_transform(trans)def draw(self, renderer):c = self.get_edgecolor()self.set_edgecolor((1,1,1,0))超级().绘制(渲染器)self.update_segments(c)self.edgelines.draw(渲染器)self.set_edgecolor(c)def update_segments(self, color):x, y = self.get_xy()w, h = self.get_width(), self.get_height()seg = np.array([[x, y], [x+w, y], [x+w, y+h],[x, y+h], [x, y]]).reshape(-1, 1, 2)段 = np.concatenate([seg[:-1], seg[1:]],axis=1)self.edgelines.set_segments(segments)self.edgelines.set_linewidth(self.get_linewidth())颜色 = [如果边缘在 self._visible_edges else (1,1,1,0) 中的颜色对于 self._edges 中的边缘]self.edgelines.set_edgecolor(颜色)def get_path(self):代码 = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY]返回路径([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]],代码,只读=真)matplotlib.table.CustomCell = MyCell数据 = [[1,2,3,4],[6,5,4,3],[1,3,5,1]]table = plt.table(cellText=data, colLabels=['A', 'B', 'C', 'D'], loc='center',cellLoc='center', colColours=['#FFFFFF', '#F3CC32', '#2769BD', '#DC3735'])table.auto_set_font_size(False)h = table.get_celld()[(0,0)].get_height()w = table.get_celld()[(0,0)].get_width()# 创建一个额外的标题header = [table.add_cell(-1,pos, w, h, loc="center", facecolor="limegreen") for pos in [1,2,3]]header[0].visible_edges = "TBL"header[1].visible_edges = "TB"header[2].visible_edges = "TBR"header[1].get_text().set_text("Header")plt.axis('关闭')plt.show()

但是请注意,由于绘制顺序的原因,对于标题文本比单元格长的情况,这将失败.

at the moment I've got this piece of code:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from matplotlib.font_manager import FontProperties


data = np.random.uniform(0, 1, 80).reshape(20, 4)
final_data = [['%.3f' % j for j in i] for i in data]

mpl.style.use('seaborn')
mpl.rc('xtick', labelsize = 7)
mpl.rc('ytick', labelsize = 7)

fig = plt.figure()

fig.subplots_adjust(left=0.1, wspace=0.1)
plt.subplot2grid((1, 4), (0, 0), colspan=3)

table_subplot = plt.subplot2grid((1, 4), (0, 3))

table = plt.table(cellText=final_data, colLabels=['A', 'B', 'C', 'D'], loc='center', cellLoc='center', colColours=['#FFFFFF', '#F3CC32', '#2769BD', '#DC3735'])
table.auto_set_font_size(False)
table.set_fontsize(7)
table.auto_set_column_width((-1, 0, 1, 2, 3))

for (row, col), cell in table.get_celld().items():
    if (row == 0):
        cell.set_text_props(fontproperties=FontProperties(weight='bold', size=7))

plt.axis('off')
plt.show()

which produce this as an ouput:

I know that the plot is empty, but I'm planning to add some data there, so I need to keep this in mind! I want to add one more row to the table to have a header. This row should only be over the last three columns, something like this:

      +-----------------+
      |      Header     |
+-----+-----------------+
|  A  |  B  |  C  |  D  |
+-----+-----+-----+-----+
| ... | ... | ... | ... |
+-----+-----+-----+-----+
| ... | ... | ... | ... |
+-----+-----+-----+-----+

The width of the header row should match the sum of the width of the A, B and C columns. I've bene playing around but I can not manage to get it... Can anyone help me?

Thanks!

解决方案

Matplotlib tables do not have the concept of "colspan" or "rowspan", where cells are span multiple columns or rows. One could think that a cell can be made three times as wide as other cells. However, that would introduce an unwanted shift

An option you have is to set the visible_edges of additional cells you manually add via .add_cell to the top of the table.

The visible edges can be "T": top, "B" : bottom, "L" : left or "R" : right.
Then setting the text to the middle cell makes the whole thing look like a single cell.

import matplotlib.pyplot as plt

data = [[1,2,3,4],[6,5,4,3],[1,3,5,1]]

table = plt.table(cellText=data, colLabels=['A', 'B', 'C', 'D'], loc='center', 
                  cellLoc='center', colColours=['#FFFFFF', '#F3CC32', '#2769BD', '#DC3735'])
table.auto_set_font_size(False)
h = table.get_celld()[(0,0)].get_height()
w = table.get_celld()[(0,0)].get_width()

# Create an additional Header
header = [table.add_cell(-1,pos, w, h, loc="center", facecolor="none") for pos in [1,2,3]]
header[0].visible_edges = "TBL"
header[1].visible_edges = "TB"
header[2].visible_edges = "TBR"
header[1].get_text().set_text("Header Header Header Header")

plt.axis('off')
plt.show()


Appendix

The above does not allow to colorize the background of a table cell. For this the following workaround can be used:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.table
from matplotlib.collections import LineCollection
from matplotlib.path import Path

class MyCell(matplotlib.table.CustomCell):
    def __init__(self, *args, visible_edges, **kwargs):
        super().__init__(*args, visible_edges=visible_edges, **kwargs)
        seg = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0],
                        [0.0, 1.0], [0.0, 0.0]]).reshape(-1, 1, 2)
        segments = np.concatenate([seg[:-1], seg[1:]], axis=1)
        self.edgelines = LineCollection(segments, edgecolor=kwargs.get("edgecolor"))
        self._text.set_zorder(2)
        self.set_zorder(1)

    def set_transform(self, trans):
        self.edgelines.set_transform(trans)
        super().set_transform(trans)

    def draw(self, renderer):
        c = self.get_edgecolor()
        self.set_edgecolor((1,1,1,0))
        super().draw(renderer)
        self.update_segments(c)
        self.edgelines.draw(renderer)
        self.set_edgecolor(c)

    def update_segments(self, color):
        x, y = self.get_xy()
        w, h = self.get_width(), self.get_height()
        seg = np.array([[x, y], [x+w, y], [x+w, y+h],
                        [x, y+h], [x, y]]).reshape(-1, 1, 2)
        segments = np.concatenate([seg[:-1], seg[1:]], axis=1)
        self.edgelines.set_segments(segments)
        self.edgelines.set_linewidth(self.get_linewidth())
        colors = [color if edge in self._visible_edges else (1,1,1,0)
                    for edge in self._edges]
        self.edgelines.set_edgecolor(colors)

    def get_path(self):
        codes = [Path.MOVETO] + [Path.LINETO]*3 + [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)



matplotlib.table.CustomCell = MyCell

data = [[1,2,3,4],[6,5,4,3],[1,3,5,1]]

table = plt.table(cellText=data, colLabels=['A', 'B', 'C', 'D'], loc='center', 
                  cellLoc='center', colColours=['#FFFFFF', '#F3CC32', '#2769BD', '#DC3735'])
table.auto_set_font_size(False)
h = table.get_celld()[(0,0)].get_height()
w = table.get_celld()[(0,0)].get_width()

# Create an additional Header
header = [table.add_cell(-1,pos, w, h, loc="center", facecolor="limegreen") for pos in [1,2,3]]
header[0].visible_edges = "TBL"
header[1].visible_edges = "TB"
header[2].visible_edges = "TBR"
header[1].get_text().set_text("Header")

plt.axis('off')
plt.show()

Note however, that this will fail for cases where the header text is longer than the cell, due to the drawing order.

这篇关于使用 matplotlib 沿图表绘制表格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆