gpt4 book ai didi

matplotlib - 在 matplotlib 中旋转图例或向轴标签添加补丁

转载 作者:行者123 更新时间:2023-12-04 01:17:15 27 4
gpt4 key购买 nike

我在 matplotlib 中有一个不寻常的用例,我正在尝试解决。我有一对使用 twinx() 创建的轴。每个只包含一个线条对象,具有不同的样式。我必须在每个轴的 y 标签上添加一个代表每条线的补丁,而不是使用传统的图例。这是我想要实现的目标:

expected

理想情况下,补丁应位于文本上方,但与实现预期结果相比,这是一个非常小的细节。

我尝试了两种方法来解决这个问题,但都以失败告终。也许 matplotlib 大师可以提供帮助:

#1:使用流离失所的图例

from matplotlib import pyplot as plt
fig = plt.figure()
ax = fig.subplots(111)
ax = fig.add_subplot(111)
ax2 = ax.twinx()
l1, = ax.plot((0, 1), (1, 0), linestyle='-', color='blue')
l2, = ax.plot((0, 1), (0, 1), linestyle='--', color='red')
leg1 = ax.legend([l1], ['Solid Blue Line'], bbox_to_anchor=(-0.102, 0., 0.102, 1.), frameon=False, mode='expand', loc=4)
leg2 = ax2.legend([l2], ['Dashed Red Line'], bbox_to_anchor=(1.102, 0., 0.102, 1.), frameon=False, mode='expand', loc=3)

正如预期的那样,这会正确放置图例,但不会旋转它们。我无法进行旋转,因为显然图例无法旋转,尽管是 Artist 扩展。例如,leg1.set_transform(leg1.get_transform() + Affine2D().rotate_deg(-90)) 不会改变图例的角度:

actual1

#2 使用自定义 AnchoredOffsetBox

在这种方法中,我尝试构建一个包含文本和补丁的自定义框。不幸的是,补丁没有正确显示。

from matplotlib import pyplot as plt
from matplotlib.lines import Line2D
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, DrawingArea, HPacker
from matplotlib.transform import Affine2D

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1, 2, 3], [0, 3, -1], color='g', linestyle='solid')
textArea = TextArea('This is an x-label')
drawArea = DrawingArea(1., 1.)
patch = Line2D((0, 1), (0, 1), color='g', linestyle='solid')
drawArea.add_artist(patch)
content = HPacker(children=[textArea, drawArea], align="center", pad=0, sep=5)
label = AnchoredOffsetbox(loc=10, child=content, pad=0, bbox_to_anchor=(0.5, -0.1), bbox_transform=ax.transAxes, frameon=False)
ax.add_artist(label)
label.set_transform(label.get_transform() + Affine2D().rotate_deg(-90))

同样,旋转根本不起作用。此外,补丁没有像在图例条目中那样合理缩放(注意标签末尾的小绿点):

actual2

是否有可能在 MatPlotLib 中实现我想要的结果?我愿意深入研究源代码,如果有帮助的话可能会提交 PR,但我不清楚从哪里开始。

更新

查看源码,完全忽略了matplotlib.offsetbox.TextAreamatplotlib.offsetbox.DrawingAreaset_transform方法。这意味着即使我能够正确绘制补丁,我的第二次尝试也毫无意义。

最佳答案

避免尝试在轴外排列框的噩梦的一种解决方案是使用带有 textcolor 的 latex 标签。以下代码

import matplotlib
matplotlib.use('ps')
from matplotlib import rc
rc('text',usetex=True)
rc('text.latex', preamble=r'\usepackage{color}')
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()
l1, = ax.plot((0, 1), (1, 0), linestyle='-', color='blue')
l2, = ax.plot((0, 1), (0, 1), linestyle='--', color='red')

ax.set_ylabel(r'\textcolor{blue}{--}' + r'$\;$ Solid Blue Line')
ax2.set_ylabel(r'\textcolor{red}{- -}' + r'$\;$ Dashed Red Line')

#may need to convert test.ps -trim test.png for picture
plt.savefig('test.ps')

测试文件的结果如下所示,

enter image description here

Latex 允许您使用\hline 来设计线条(或将 \n\usepackage{dashrule} 添加到序言),\circle 等用于标记,您选择的颜色,您可以使用\;

更新:标记、颜色和线条样式的更多示例,

import matplotlib
matplotlib.use('ps')
from matplotlib import rc
rc('text',usetex=True)
latex_pream = matplotlib.rcParams['text.latex.preamble']
latex_pream.append(r'\usepackage{color}')
latex_pream.append(r"\definecolor{lllgrey}{rgb}{0.9,0.9,0.9}")
latex_pream.append(r"\definecolor{lightblue}{rgb}{0.56485968018118948, 0.7663975529283894, 0.86758939636894861}")
latex_pream.append(r"\newcommand*{\xlinethick}[1][1.0em]{\rule[0.4ex]{#1}{1.5pt}}")
latex_pream.append(r"\newcommand*{\xdashthick}[1][1.0em]{\rule[0.5ex]{2.5pt}{1.5pt} $\!$ \rule[0.5ex]{2.5pt}{1.5pt}}")

import matplotlib.pyplot as plt

plt.text(0.1,0.5,"Latex marker and line examples: \n $\;\;\;\;\;$ \{"
+ r'\textcolor{blue}{$ - - \!\!\!\!\!\!\!\! \bullet \;$} ' + ',$\;\;$'
+ r'\textcolor{red}{$\bullet$} $\!\!\!\!\! \:\! \circ$' + ',$\;\;$'
+ r'\textcolor{lllgrey}{\xlinethick}' + ',$\;\;$'
+ r'\textcolor{lightblue}{\xdashthick}' + ' \}', fontsize=24)

#may need to convert test.ps -trim test.png for picture
plt.savefig('test.ps')

结果是

enter image description here

关于matplotlib - 在 matplotlib 中旋转图例或向轴标签添加补丁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38002700/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com