【问题标题】:Text position changes when a Matplotlib figure is saved in SVG当 Matplotlib 图形保存在 SVG 中时,文本位置发生变化
【发布时间】:2022-01-19 18:25:03
【问题描述】:

Python 3.9.0 Matplotlib 3.5.1

我绘制了一个表格并通过this method 合并了单元格。然而,MPL 图中的输出看起来不错,但如果我将其保存为 SVG 格式,那么它会变得很奇怪。此外,当我通过 Inkscape 将文件转换为 EMF 格式时,情况变得更糟。如何将图形保存为图形句柄中所示的 SVG 格式? (位图格式-jpg、png、..-没问题)

可重现的代码

import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

def mergecells(table, cells):
    '''
    Merge N matplotlib.Table cells

    Parameters
    -----------
    table: matplotlib.Table
        the table
    cells: list[set]
        list of sets od the table coordinates
        - example: [(0,1), (0,0), (0,2)]

    Notes
    ------
    https://stackoverflow.com/a/53819765/12684122
    '''
    cells_array = [np.asarray(c) for c in cells]
    h = np.array([cells_array[i+1][0] - cells_array[i][0] for i in range(len(cells_array) - 1)])
    v = np.array([cells_array[i+1][1] - cells_array[i][1] for i in range(len(cells_array) - 1)])

    # if it's a horizontal merge, all values for `h` are 0
    if not np.any(h):
        # sort by horizontal coord
        cells = np.array(sorted(list(cells), key=lambda v: v[1]))
        edges = ['BTL'] + ['BT' for i in range(len(cells) - 2)] + ['BTR']
    elif not np.any(v):
        cells = np.array(sorted(list(cells), key=lambda h: h[0]))
        edges = ['TRL'] + ['RL' for i in range(len(cells) - 2)] + ['BRL']
    else:
        raise ValueError("Only horizontal and vertical merges allowed")

    for cell, e in zip(cells, edges):
        table[cell[0], cell[1]].visible_edges = e
        
    txts = [table[cell[0], cell[1]].get_text() for cell in cells]
    tpos = [np.array(t.get_position()) for t in txts]

    # transpose the text of the left cell
    trans = (tpos[-1] - tpos[0])/2
    # didn't had to check for ha because I only want ha='center'
    txts[0].set_transform(mpl.transforms.Affine2D().translate(*trans))
    for txt in txts[1:]:
        txt.set_visible(False)

df = pd.DataFrame()
df['Animal'] = ['Cow', 'Bear']
df['Weight'] = [250, 450]
df['Favorite'] = ['Grass', 'Honey']
df['Least Favorite'] = ['Meat', 'Leaves']

fig = plt.figure(figsize=(9,2))
ax=fig.gca()
ax.axis('off')
r,c = df.shape

# plot the real table
table = ax.table(cellText=np.vstack([df.columns, df.values]), 
                 cellColours=[['none']*c]*(r+1),
                 bbox=[0, 0, 1, 1],
                 cellLoc="center")

# need to draw here so the text positions are calculated
fig.canvas.draw()

mergecells(table, [(0,0),(1,0),(2,0)])

fig.savefig("svgoutput.svg")
plt.show()

MPL图形句柄中显示的图像

保存的 SVG 文件中显示的图像

您可以看到合并单元格(“动物”)中的文本下降。虽然我没有附上 EMF 文件,但它进一步向下,甚至一些文本消失了。

【问题讨论】:

  • 您正在获取数据坐标中的文本位置,然后添加一个转换来进行翻译。这对我来说似乎很脆弱——为什么不直接改变文本的位置呢?但我并没有尝试遵循所有步骤,也许这不是问题。
  • txts[0].set_position() 根本不影响它的位置。我不知道为什么。

标签: python matplotlib svg


【解决方案1】:

在绘图之前设置后端解决了这个问题。

import matplotlib as mpl

# This line must comes before plotting a figure
mpl.use("SVG")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-22
    • 2021-09-08
    • 1970-01-01
    • 2019-02-27
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 2013-07-02
    相关资源
    最近更新 更多