如何使 Matplotlib 表格单元格颜色与不可见的单元格边缘一起使用?

发布于 2025-01-17 12:07:43 字数 2566 浏览 2 评论 0原文

我正在尝试使用 matplotlib 创建一个表,其中有一些列应该通过不共享边框在视觉上连接,并且也应该着色。 现在我可以做其中之一,但我似乎不能同时做两者,因为设置边框边缘不可见会破坏颜色。

它的颜色看起来应该是这样的: 颜色正确

边缘的外观: Edges Correct

当我将两者结合起来时,它现在的样子: 应用边缘和颜色这是我生成 borked 结果的示例代码。您可以通过注释掉 plt.show() 上面的 for 循环来创建正确的颜色。如果我将所有边缘设置为 BTLR(= 全边缘),颜色就会再次正常。

如果我可以将第一张图像中的线条设置为比其他图像更粗,它也对我有用,但我也没有找到一种方法来做到这一点。

任何帮助将不胜感激。对我来说似乎是 matplotlib 中的一个错误?有解决方法吗? 也许我需要用plotly或其他一些工具来完成它,但我以前从未使用过plotly,而且与matplotlib相比,它似乎没有很多简单的帮助......

import math
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')

dpi_value = 100
picture_size_x = 1200
picture_size_y = 600

fig, axs = plt.subplots(figsize=(picture_size_x / dpi_value, picture_size_y / dpi_value), dpi=dpi_value)
axs.axis('tight')
axs.axis('off')
data = [[  66386,  174296,   75131,  577908,   32015, 49682, 76314],
        [  58230,  381139,   78045,   99308,  160454, 74674, 64311],
        [  89135,   80552,  152558,  497981,  603535, 75312, 25687],
        [  78415,   81858,  150656,  193263,   69638, 14566, 48753],
        [ 139361,  331509,  343164,  781380,   52269, 54378, 64745]]


cellcolours_array = [['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan']]

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

the_table = plt.table(cellText=data,
                      cellColours=cellcolours_array,
                      rowLabels=rows,
                      colLabels=columns,
                      cellLoc='center',
                      bbox=[0.0, 0.0, 1.0, 1.0]
                      )

# this here doesnt work right
for row_idx in range(len(data)+1):
    for col_idx in range(len(data[0])):
        edges = 'horizontal'
        if col_idx == 0:
            edges = 'BTL'
        if (col_idx+1) % 3 == 0:
            edges = 'BTR'
            ccolor = 'silver'
        if (col_idx+1) == len(data[0]):
            edges = 'BTR'
        the_table[row_idx, col_idx].visible_edges = edges
plt.show()

我尝试尝试颜色,facecolor,填充和其他的事情都无济于事。我知道我可以将线宽全局设置为 0,但这对我没有帮助,因为我需要一些线......

I am trying to create a table with matplotlib that has some columns that should be visually joined by not sharing borders, and also be colored.
Now I can do one or the other, but I can't seem to do both as the setting border edges invisible screws up the colors.

The way it should look with the colors:
Colors correct

The way it should look with the edges:
Edges correct

The way it now looks when I combine both:
Edges and colors appliedThis is my example code producing the borked result. You can create the correct colors by commenting out the for loop above plt.show(). If I set all edges to BTLR (= full edges) the colors are fine again.

It would also work for me if I could set the lines from the first image as bolder than the others, but I did not find a way to do that either.

Any help would be appreciated. Seems like a bug in matplotlib to me? Is there a workaround?
Maybe I need to do it in plotly or some other tool, but I have never used plotly before and there seems to be a lot less uncomplicated help around for it as compared to matplotlib...

import math
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')

dpi_value = 100
picture_size_x = 1200
picture_size_y = 600

fig, axs = plt.subplots(figsize=(picture_size_x / dpi_value, picture_size_y / dpi_value), dpi=dpi_value)
axs.axis('tight')
axs.axis('off')
data = [[  66386,  174296,   75131,  577908,   32015, 49682, 76314],
        [  58230,  381139,   78045,   99308,  160454, 74674, 64311],
        [  89135,   80552,  152558,  497981,  603535, 75312, 25687],
        [  78415,   81858,  150656,  193263,   69638, 14566, 48753],
        [ 139361,  331509,  343164,  781380,   52269, 54378, 64745]]


cellcolours_array = [['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan']]

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

the_table = plt.table(cellText=data,
                      cellColours=cellcolours_array,
                      rowLabels=rows,
                      colLabels=columns,
                      cellLoc='center',
                      bbox=[0.0, 0.0, 1.0, 1.0]
                      )

# this here doesnt work right
for row_idx in range(len(data)+1):
    for col_idx in range(len(data[0])):
        edges = 'horizontal'
        if col_idx == 0:
            edges = 'BTL'
        if (col_idx+1) % 3 == 0:
            edges = 'BTR'
            ccolor = 'silver'
        if (col_idx+1) == len(data[0]):
            edges = 'BTR'
        the_table[row_idx, col_idx].visible_edges = edges
plt.show()

I tried experimenting with color, facecolor, fill and other things to no avail. I know I can set linewidth to 0 globally, but that won't help me as I need some lines...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

起风了 2025-01-24 12:07:43

经过一番深入思考,我想出了一个有效的创可贴解决方案:

我现在正在创建两张表格,一张的边缘像我想要的那样可见,并且单元格是透明的,另一张是彩色的单元格,没有边缘。两者都具有相同的 bbox,边缘表位于顶部,具有较高的 zorder 值。瞧,我得到了想要的结果:

现在全部正确

这是代码:

import math
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')

dpi_value = 100
picture_size_x = 1200
picture_size_y = 600

fig, axs = plt.subplots(figsize=(picture_size_x / dpi_value, picture_size_y / dpi_value), dpi=dpi_value)
axs.axis('tight')
axs.axis('off')

data = [[  66386,  174296,   75131,  577908,   32015, 49682, 76314],
        [  58230,  381139,   78045,   99308,  160454, 74674, 64311],
        [  89135,   80552,  152558,  497981,  603535, 75312, 25687],
        [  78415,   81858,  150656,  193263,   69638, 14566, 48753],
        [ 139361,  331509,  343164,  781380,   52269, 54378, 64745]]

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

edges_table = plt.table(cellText=data,
                        rowLabels=rows,
                        colLabels=columns,
                        cellLoc='center',
                        bbox=[0.0, 0.0, 1.0, 1.0],
                        zorder=10
                        )

for row_idx in range(len(data)+1):
    for col_idx in range(len(data[0])):
        edges = 'horizontal'
        if col_idx == 0:
            edges = 'BTL'
        if (col_idx+1) % 3 == 0:
            edges = 'BTR'
        if (col_idx+1) == len(data[0]):
            edges = 'BTR'
        edges_table[row_idx, col_idx].visible_edges = edges

cellcolours_array = [['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan']]

colors_table = plt.table(cellText=data,
                         cellColours=cellcolours_array,
                         rowLabels=rows,
                         colLabels=columns,
                         cellLoc='center',
                         bbox=[0.0, 0.0, 1.0, 1.0],
                         zorder=1
                         )

for child in edges_table.get_children():
    child.set(facecolor=(1.0, 1.0, 1.0, 0.0))
    child.set_text_props(color=(1.0, 1.0, 1.0, 0.0))
for child in colors_table.get_children():
    child.set(linewidth=0)
plt.show()

After some deep thinking, I came up with a bandaid solution that works:

I am now creating two tables, one with the edges visible like I want and transparent cells, and one with the colored cells and no edges. Both with the same bbox, the edges-table on top with the higher zorder value. Et voila, I get the desired result:

all correct now

Here is the code:

import math
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')

dpi_value = 100
picture_size_x = 1200
picture_size_y = 600

fig, axs = plt.subplots(figsize=(picture_size_x / dpi_value, picture_size_y / dpi_value), dpi=dpi_value)
axs.axis('tight')
axs.axis('off')

data = [[  66386,  174296,   75131,  577908,   32015, 49682, 76314],
        [  58230,  381139,   78045,   99308,  160454, 74674, 64311],
        [  89135,   80552,  152558,  497981,  603535, 75312, 25687],
        [  78415,   81858,  150656,  193263,   69638, 14566, 48753],
        [ 139361,  331509,  343164,  781380,   52269, 54378, 64745]]

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

edges_table = plt.table(cellText=data,
                        rowLabels=rows,
                        colLabels=columns,
                        cellLoc='center',
                        bbox=[0.0, 0.0, 1.0, 1.0],
                        zorder=10
                        )

for row_idx in range(len(data)+1):
    for col_idx in range(len(data[0])):
        edges = 'horizontal'
        if col_idx == 0:
            edges = 'BTL'
        if (col_idx+1) % 3 == 0:
            edges = 'BTR'
        if (col_idx+1) == len(data[0]):
            edges = 'BTR'
        edges_table[row_idx, col_idx].visible_edges = edges

cellcolours_array = [['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan'],
        ['green', 'green', 'green', 'orange', 'orange', 'orange', 'cyan']]

colors_table = plt.table(cellText=data,
                         cellColours=cellcolours_array,
                         rowLabels=rows,
                         colLabels=columns,
                         cellLoc='center',
                         bbox=[0.0, 0.0, 1.0, 1.0],
                         zorder=1
                         )

for child in edges_table.get_children():
    child.set(facecolor=(1.0, 1.0, 1.0, 0.0))
    child.set_text_props(color=(1.0, 1.0, 1.0, 0.0))
for child in colors_table.get_children():
    child.set(linewidth=0)
plt.show()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文