gpt4 book ai didi

python - 如何使标题框的宽度跨越整个绘图?

转载 作者:太空狗 更新时间:2023-10-29 17:01:10 32 4
gpt4 key购买 nike

考虑以下 pandas 系列 s 和 plot

import pandas as pd
import numpy as np

s = pd.Series(np.random.lognormal(.001, .01, 100))
ax = s.cumprod().plot()
ax.set_title('My Log Normal Example', position=(.5, 1.02),
backgroundcolor='black', color='white')

enter image description here

如何让包含标题的框横跨整个图?

最佳答案

当然可以获取标题的边界框,它是一个 Text 元素。这可以通过

title = ax.set_title(...) 
bb = title.get_bbox_patch()

原则上,然后可以操纵边界框,例如通过bb.set_width(...)。但是,一旦 matplotlib 将标题绘制到 Canvas 上,所有设置都会丢失。至少我是这样解释 Textdraw() 方法的。

我不知道设置边界框的其他方法。例如,legend 的边界框可以通过
设置plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, mode="expand") 使其在整个轴范围内扩展(参见 here ).如果 Text 也有相同的选项,那将非常有用。但就目前而言,我们没有。

Text 对象允许设置 bbox通常用于设置边界框样式的参数。无法设置边界框范围,但它接受周围框的一些属性字典。接受的属性之一是 boxstyle .默认情况下,这是一个正方形,但可以设置为圆形或箭头或其他奇怪的形状。

那些 boxstyle 实际上是可能解决方案的关键。它们都继承自 BoxStyle._Base 并且 - 如 the bottom of the annotations guide 所示- 可以定义自定义形状,继承 BoxStyle._Base

以下解决方案基于 BoxStyle._Base 的子类化,它接受轴的宽度作为参数并绘制标题的矩形路径,使其恰好具有此宽度.

作为奖励,我们可以注册一个事件处理程序,以便此宽度一旦因调整窗口大小而发生变化,就会进行调整。

代码如下:

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

from matplotlib.path import Path
from matplotlib.patches import BoxStyle


class ExtendedTextBox(BoxStyle._Base):
"""
An Extended Text Box that expands to the axes limits
if set in the middle of the axes
"""

def __init__(self, pad=0.3, width=500.):
"""
width:
width of the textbox.
Use `ax.get_window_extent().width`
to get the width of the axes.
pad:
amount of padding (in vertical direction only)
"""
self.width=width
self.pad = pad
super(ExtendedTextBox, self).__init__()

def transmute(self, x0, y0, width, height, mutation_size):
"""
x0 and y0 are the lower left corner of original text box
They are set automatically by matplotlib
"""
# padding
pad = mutation_size * self.pad

# we add the padding only to the box height
height = height + 2.*pad
# boundary of the padded box
y0 = y0 - pad
y1 = y0 + height
_x0 = x0
x0 = _x0 +width /2. - self.width/2.
x1 = _x0 +width /2. + self.width/2.

cp = [(x0, y0),
(x1, y0), (x1, y1), (x0, y1),
(x0, y0)]

com = [Path.MOVETO,
Path.LINETO, Path.LINETO, Path.LINETO,
Path.CLOSEPOLY]

path = Path(cp, com)

return path

dpi = 80

# register the custom style
BoxStyle._style_list["ext"] = ExtendedTextBox

plt.figure(dpi=dpi)
s = pd.Series(np.random.lognormal(.001, .01, 100))
ax = s.cumprod().plot()
# set the title position to the horizontal center (0.5) of the axes
title = ax.set_title('My Log Normal Example', position=(.5, 1.02),
backgroundcolor='black', color='white')
# set the box style of the title text box toour custom box
bb = title.get_bbox_patch()
# use the axes' width as width of the text box
bb.set_boxstyle("ext", pad=0.4, width=ax.get_window_extent().width )


# Optionally: use eventhandler to resize the title box, in case the window is resized
def on_resize(event):
print "resize"
bb.set_boxstyle("ext", pad=0.4, width=ax.get_window_extent().width )

cid = plt.gcf().canvas.mpl_connect('resize_event', on_resize)

# use the same dpi for saving to file as for plotting on screen
plt.savefig(__file__+".png", dpi=dpi)
plt.show()

enter image description here


如果有人对更轻的解决方案感兴趣,还可以选择使用标题边界框的 mutation_aspect,在绘制标题时显然保持不变。虽然 mutation_aspect 本身基本上只改变框的高度,但可以为框使用非常大的填充并将 mutation_aspect 设置为非常小的数字,这样在最后框出现在宽度扩展。这个解决方案的明显缺点是,填充和纵横比的值必须通过反复试验找到,并且会随着不同的字体和图形大小而变化。在我的例子中,mutation_aspect = 0.04pad=11.9 的值产生了期望的结果,但在其他系统上,它们当然可能不同。

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

s = pd.Series(np.random.lognormal(.001, .01, 100))
ax = s.cumprod().plot()
title = ax.set_title('My Log Normal Example', position=(.5, 1.02),
backgroundcolor='black', color='white',
verticalalignment="bottom", horizontalalignment="center")
title._bbox_patch._mutation_aspect = 0.04
title.get_bbox_patch().set_boxstyle("square", pad=11.9)
plt.tight_layout()
plt.savefig(__file__+".png")
plt.show()

关于python - 如何使标题框的宽度跨越整个绘图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40796117/

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