【问题标题】:Drawing arrows between two tables (as an image) (Python)在两个表之间绘制箭头(作为图像)(Python)
【发布时间】:2020-09-13 00:18:10
【问题描述】:

我想绘制一张相邻的两张桌子,箭头以特定方式在它们之间射出(matplotlib)。到目前为止,我或多或少都知道如何使用plt.arrow 来让箭头做我想做的事情,并且我找到了一篇文章,展示了如何仅绘制plt.table 的表格部分。

https://towardsdatascience.com/simple-little-tables-with-matplotlib-9780ef5d0bc4

源代码,以防链接失效:

import numpy as np
import matplotlib.pyplot as plt
title_text = 'Loss by Disaster'
footer_text = 'June 24, 2020'
fig_background_color = 'skyblue'
fig_border = 'steelblue'
data =  [
            [         'Freeze', 'Wind', 'Flood', 'Quake', 'Hail'],
            [ '5 year',  66386, 174296,   75131,  577908,  32015],
            ['10 year',  58230, 381139,   78045,   99308, 160454],
            ['20 year',  89135,  80552,  152558,  497981, 603535],
            ['30 year',  78415,  81858,  150656,  193263,  69638],
            ['40 year', 139361, 331509,  343164,  781380,  52269],
        ]
# Pop the headers from the data array
column_headers = data.pop(0)
row_headers = [x.pop(0) for x in data]
# Table data needs to be non-numeric text. Format the data
# while I'm at it.
cell_text = []
for row in data:
    cell_text.append([f'{x/1000:1.1f}' for x in row])
# Get some lists of color specs for row and column headers
rcolors = plt.cm.BuPu(np.full(len(row_headers), 0.1))
ccolors = plt.cm.BuPu(np.full(len(column_headers), 0.1))
# Create the figure. Setting a small pad on tight_layout
# seems to better regulate white space. Sometimes experimenting
# with an explicit figsize here can produce better outcome.
plt.figure(linewidth=2,
           edgecolor=fig_border,
           facecolor=fig_background_color,
           tight_layout={'pad':1},
           #figsize=(5,3)
          )
# Add a table at the bottom of the axes
the_table = plt.table(cellText=cell_text,
                      rowLabels=row_headers,
                      rowColours=rcolors,
                      rowLoc='right',
                      colColours=ccolors,
                      colLabels=column_headers,
                      loc='center')
# Scaling is the only influence we have over top and bottom cell padding.
# Make the rows taller (i.e., make cell y scale larger).
the_table.scale(1, 1.5)
# Hide axes
ax = plt.gca()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# Hide axes border
plt.box(on=None)
# Add title
plt.suptitle(title_text)
# Add footer
plt.figtext(0.95, 0.05, footer_text, horizontalalignment='right', size=6, weight='light')
# Force the figure to update, so backends center objects correctly within the figure.
# Without plt.draw() here, the title will center on the axes and not the figure.
plt.draw()
# Create image. plt.savefig ignores figure edge and face colors, so map them.
fig = plt.gcf()
plt.savefig('pyplot-table-demo.png',
            #bbox='tight',
            edgecolor=fig.get_edgecolor(),
            facecolor=fig.get_facecolor(),
            dpi=150
            )

但是,我无法让两个表格彼此相邻并且看起来不错,并且两者之间的箭头不会穿过两个绘图区域。

import numpy as np
import matplotlib.pyplot as plt

fig, (ax1, ax2) = plt.subplots(1, 2)


title_text = 'Loss by Disaster'
footer_text = 'June 24, 2020'
fig_background_color = 'skyblue'
fig_border = 'steelblue'
data =  [
            [         'Freeze', 'Wind', 'Flood', 'Quake', 'Hail'],
            [ '5 year',  66386, 174296,   75131,  577908,  32015],
            ['10 year',  58230, 381139,   78045,   99308, 160454],
            ['20 year',  89135,  80552,  152558,  497981, 603535],
            ['30 year',  78415,  81858,  150656,  193263,  69638],
            ['40 year', 139361, 331509,  343164,  781380,  52269],
        ]
# Pop the headers from the data array
column_headers = data.pop(0)
row_headers = [x.pop(0) for x in data]
# Table data needs to be non-numeric text. Format the data
# while I'm at it.
cell_text = []
for row in data:
    cell_text.append([f'{x/1000:1.1f}' for x in row])
# Get some lists of color specs for row and column headers
rcolors = plt.cm.BuPu(np.full(len(row_headers), 0.1))
ccolors = plt.cm.BuPu(np.full(len(column_headers), 0.1))
# Create the figure. Setting a small pad on tight_layout
# seems to better regulate white space. Sometimes experimenting
# with an explicit figsize here can produce better outcome.
# ax1.figure(linewidth=2,
#            edgecolor=fig_border,
#            facecolor=fig_background_color,
#            tight_layout={'pad':1},
#            #figsize=(5,3)
#           )
# Add a table at the bottom of the axes
the_table = ax1.table(cellText=cell_text,
                      rowLabels=row_headers,
                      rowColours=rcolors,
                      rowLoc='right',
                      colColours=ccolors,
                      colLabels=column_headers,
                      loc='center')
# Scaling is the only influence we have over top and bottom cell padding.
# Make the rows taller (i.e., make cell y scale larger).
the_table.scale(1, 1.5)
# Hide axes
ax1 = plt.gca()
ax1.get_xaxis().set_visible(False)
ax1.get_yaxis().set_visible(False)
#
# Do it again
#
the_table = ax2.table(cellText=cell_text,
                      rowLabels=row_headers,
                      rowColours=rcolors,
                      rowLoc='right',
                      colColours=ccolors,
                      colLabels=column_headers,
                      loc='center')
# Scaling is the only influence we have over top and bottom cell padding.
# Make the rows taller (i.e., make cell y scale larger).
the_table.scale(1, 1.5)
# Hide axes
ax2 = plt.gca()
ax2.get_xaxis().set_visible(False)
ax2.get_yaxis().set_visible(False)
#
plt.arrow(0.5, 0.5, -5, 1)

do it again 或许可以用一个函数来整理。)

最终,我想要得到类似下面的草图。

我愿意对我的方法进行细微的调整,以完成改变我正在做的事情,甚至不使用matplotlib,但我怎样才能将我的想法转化为一些代码,从而产生类似于我的草图的东西?

【问题讨论】:

    标签: python matplotlib plot


    【解决方案1】:

    你快到了(可能同时已经解决了它),缺少的要点是你需要创建一个箭头(或者更确切地说是一个ConnectionPatch),它需要与整个图形(即@ 987654326@) 而不是仅使用单个子图作为参考。请注意,此解决方案是adapted from this answerhere 是一些相关文档。

    完整代码:

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.patches import ConnectionPatch
    
    fig, (ax1, ax2) = plt.subplots(1, 2,figsize=(10,5))
    
    title_text = 'Loss by Disaster'
    footer_text = 'June 24, 2020'
    fig_background_color = 'skyblue'
    fig_border = 'steelblue'
    data =  [
                [         'Freeze', 'Wind', 'Flood', 'Quake', 'Hail'],
                [ '5 year',  66386, 174296,   75131,  577908,  32015],
                ['10 year',  58230, 381139,   78045,   99308, 160454],
                ['20 year',  89135,  80552,  152558,  497981, 603535],
                ['30 year',  78415,  81858,  150656,  193263,  69638],
                ['40 year', 139361, 331509,  343164,  781380,  52269],
            ]
    # Pop the headers from the data array
    column_headers = data.pop(0)
    row_headers = [x.pop(0) for x in data]
    # Table data needs to be non-numeric text. Format the data
    # while I'm at it.
    cell_text = []
    for row in data:
        cell_text.append([f'{x/1000:1.1f}' for x in row])
    # Get some lists of color specs for row and column headers
    rcolors = plt.cm.BuPu(np.full(len(row_headers), 0.1))
    ccolors = plt.cm.BuPu(np.full(len(column_headers), 0.1))
    # Create the figure. Setting a small pad on tight_layout
    # seems to better regulate white space. Sometimes experimenting
    # with an explicit figsize here can produce better outcome.
    # ax1.figure(linewidth=2,
    #            edgecolor=fig_border,
    #            facecolor=fig_background_color,
    #            tight_layout={'pad':1},
    #            #figsize=(5,3)
    #           )
    # Add a table at the bottom of the axes
    the_table = ax1.table(cellText=cell_text,
                          rowLabels=row_headers,
                          rowColours=rcolors,
                          rowLoc='right',
                          colColours=ccolors,
                          colLabels=column_headers,
                          loc='center')
    # Scaling is the only influence we have over top and bottom cell padding.
    # Make the rows taller (i.e., make cell y scale larger).
    the_table.scale(1, 1.5)
    
    # Do it again
    #
    the_table = ax2.table(cellText=cell_text,
                          rowLabels=row_headers,
                          rowColours=rcolors,
                          rowLoc='right',
                          colColours=ccolors,
                          colLabels=column_headers,
                          loc='center')
    # Scaling is the only influence we have over top and bottom cell padding.
    # Make the rows taller (i.e., make cell y scale larger).
    the_table.scale(1, 1.5)
    
    ### actually turn axes off:
    for a in [ax1,ax2]:
        a.set_axis_off()
    
    con = ConnectionPatch(xyA=(0.38,0.4), xyB=(0.43, 0.52), 
                          coordsA="data", coordsB="data",
                          axesA=ax1, axesB=ax2,
                          shrinkA=1, shrinkB=1,
                          ec="red", fc="w", linewidth=2, alpha=1,
                          arrowstyle="-|>",connectionstyle="arc3", 
                          mutation_scale=20, )
    ax2.add_artist(con)
    
    plt.show()
    

    生成此图像:

    注意箭头起点和终点在子图坐标中是如何给出的(例如(0.38,0.4),即您应该能够通过鼠标悬停快速找到好点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多