PyPlot.Table 使用不同的列跨度和行跨度

问题描述 投票:0回答:1

我正在寻找一种方法来添加可以跨越多行的列以及可以跨越多列的行。

我目前有下面的代码来获取第一行。

# Calculate log-scaled widths
table_widths = [0.001, 0.002, 0.063, 2.0, 63.0, 150.0]
log_table_widths = np.diff(np.log10(table_widths))
log_table_widths = log_table_widths / log_table_widths.sum()

# Normalize widths to sum to 1
log_table_widths = log_table_widths / log_table_widths.sum()

table = ax.table(cellText=[['Clay', 'Silt', 'Sand', 'Gravel', 'Cobbles']], cellLoc='center', loc='bottom', colWidths=log_table_widths)
table_widths = []
table.auto_set_font_size(False)
table.set_fontsize(8)
table.scale(1, 1.5)

得到如下结果: Current Result

但是,我需要在表中添加另一行,其中一些列跨越下一行。而当前行上的单元格必须跨越多列。就像这样: Wanted Result 最好是底行是顶行,但也不是灾难。

我尝试过单独解决此问题并从 GitHub CoPilot 和 MS CoPilot 获得帮助。然而,不幸的是,我们能想到的最好的办法是:

# Calculate log-scaled widths
table_widths = [0.001, 0.002, 0.063, 2.0, 63.0, 150.0]
log_table_widths = np.diff(np.log10(table_widths))
log_table_widths = log_table_widths / log_table_widths.sum()

# Normalize widths to sum to 1
log_table_widths = log_table_widths / log_table_widths.sum()

# Create the table
cell_text = [
  ['Clay', 'Silt', 'Fine', 'Medium', 'Coarse', 'Fine', 'Medium', 'Coarse'],
  ['', '', 'Sand', 'Sand', 'Sand', 'Gravel', 'Gravel', 'Gravel'],
]
col_labels = ['Clay', 'Silt', 'Fine', 'Medium', 'Coarse', 'Fine', 'Medium', 'Coarse']
col_widths = [log_table_widths, log_table_widths, log_table_widths/3, log_table_widths/3, log_table_widths/3, log_table_widths/3, log_table_widths/3, log_table_widths/3]

# Add the table to the plot
table = ax.table(cellText=cell_text, colLabels=col_labels, cellLoc='center', loc='bottom', colWidths=col_widths)
table.auto_set_font_size(False)
table.set_fontsize(8)
table.scale(1, 1.5)

# Adjust cell alignment to avoid ambiguity
for key, cell in table.get_celld().items():
  cell.set_text_props(ha='center', va='center')

给我以下错误:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

不知道如何解决。

为了重现性,您可以使用:

fig, ax = plt.subplots()
fig.set_figwidth(18)
fig.set_figheight(12)
fig.set_dpi(80)
# draw vertical line at: 0.002mm, 0.063mm, 2.0mm, 63mm
ax.axvline(x=0.002, color='red', linestyle='--')
ax.axvline(x=0.063, color='red', linestyle='--')
ax.axvline(x=2.0, color='red', linestyle='--')
ax.axvline(x=63.0, color='red', linestyle='--')
ax.set_xlim(0.001, 150)

# Calculate log-scaled widths
table_widths = [0.001, 0.002, 0.063, 2.0, 63.0, 150.0]
log_table_widths = np.diff(np.log10(table_widths))
log_table_widths = log_table_widths / log_table_widths.sum()

# Normalize widths to sum to 1
log_table_widths = log_table_widths / log_table_widths.sum()

# Create the table
cell_text = [
  ['Clay', 'Silt', 'Fine', 'Medium', 'Coarse', 'Fine', 'Medium', 'Coarse'],
  ['', '', 'Sand', 'Sand', 'Sand', 'Gravel', 'Gravel', 'Gravel'],
]
col_labels = ['Clay', 'Silt', 'Fine', 'Medium', 'Coarse', 'Fine', 'Medium', 'Coarse']
col_widths = [log_table_widths, log_table_widths, log_table_widths/3, log_table_widths/3, log_table_widths/3, log_table_widths/3, log_table_widths/3, log_table_widths/3]

# Add the table to the plot
table = ax.table(cellText=cell_text, colLabels=col_labels, cellLoc='center', loc='bottom', colWidths=col_widths)
table.auto_set_font_size(False)
table.set_fontsize(8)
table.scale(1, 1.5)

# Adjust cell alignment to avoid ambiguity
for key, cell in table.get_celld().items():
  cell.set_text_props(ha='center', va='center')

fig.savefig('fig.png', format='png', bbox_inches='tight')

编辑: 我已经设法摆脱了这个错误。这是由定义 col_widths 变量引起的,我用列表而不是相应的值填充它。 我现在已经这样定义了,以后可能会找到更好的解决方案。

col_widths = [log_table_widths[0], log_table_widths[1], log_table_widths[2] / 3, log_table_widths[2] / 3, log_table_widths[2] / 3, log_table_widths[3] / 3, log_table_widths[3] / 3, log_table_widths[3] / 3, log_table_widths[4]]

我的桌子现在看起来像这样: New Result

虽然我还没有弄清楚如何合并行和单元格。 我确实找到了这篇文章:Matplotlib table with double headers 创建多个表以显示多个标题。但遗憾的是,这不适用于合并一列和一行中的单元格。

python matplotlib matplotlibpyplot
1个回答
0
投票

你的错误是

log_table_widths
是一个数组,而不是一个标量。

Matplotlib 表格不支持合并单元格。您可以通过删除单元格边缘来模拟它:

import matplotlib.pyplot as plt
import matplotlib.table as mtable
import numpy as np

xlims = [0.001, 150]
hlines = [0.002, 0.063, 2.0, 63.0]

fig, ax = plt.subplots(figsize=(18,12), dpi=80)
ax.set(xscale='log', xlim=xlims)
ax.xaxis.set_visible(False)

for x in hlines:
  ax.axvline(x=x, color='red', linestyle='--')

log_table_widths = np.diff(np.log10(np.r_[xlims[0], hlines, xlims[1]]))
log_table_widths /= log_table_widths.sum()
log_table_widths  = np.r_[
     log_table_widths[0],
     log_table_widths[1] / 3,
     log_table_widths[1] / 3,
     log_table_widths[1] / 3,
     log_table_widths[2] / 3,
     log_table_widths[2] / 3,
     log_table_widths[2] / 3,
     log_table_widths[3] / 3,
     log_table_widths[3] / 3,
     log_table_widths[3] / 3,                          
     log_table_widths[4]
     ]

texts = [
    ['', 'Fine', 'Middle', 'Coarse','Fine', 'Middle', 'Coarse', 'Fine', 'Middle', 'Coarse', ''],
    ['Clay', '','Silt','', '', 'Sand', '', '','Gravel','', 'Cobbles'],
]

table = ax.table(cellText=texts, cellLoc='center', loc='bottom', colWidths=log_table_widths, fontsize=8)
table.scale(1, 1.5)
for c in range(2, 9, 3):
  table.get_celld()[(1,c-1)].visible_edges='BTL'
  table.get_celld()[(1,c)].visible_edges='BT'
  table.get_celld()[(1,c+1)].visible_edges='BTR'

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.