piR*_*red 16 python matplotlib pandas
考虑下面的熊猫系列s和情节
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')
Run Code Online (Sandbox Code Playgroud)
如何让包含标题的框跨越整个图?
Imp*_*est 24
当然可以获得标题的边界框,这是一个Text元素.这可以通过以下方式完成
title = ax.set_title(...)
bb = title.get_bbox_patch()
Run Code Online (Sandbox Code Playgroud)
原则上,人们可以操纵边界框,例如通过
bb.set_width(...).但是,一旦matplotlib将标题绘制到画布上,所有设置都将丢失.至少这是我的interprete Text的draw()方法.
我不知道设置边界框的其他方法.例如,legend可以设置一个边界框
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, mode="expand"),使其在整个轴范围内扩展(参见此处).同样拥有相同的选项也非常有用Text.但就目前而言,我们没有.
该Text对象允许设置一个bbox通常用于设置边界框样式的参数.无法设置边界框范围,但它接受周围框的属性字典.其中一个被接受的属性是boxstyle.默认情况下,这是一个square,但可以设置为圆形或箭头或其他奇怪的形状.
这些boxstyle实际上是解决方案的关键.它们都继承自BoxStyle._Base- 并且 - 可以在注释指南的底部看到- 可以定义自定义形状,子类化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()
Run Code Online (Sandbox Code Playgroud)
为了防止有人对更轻的解决方案感兴趣,还可以选择使用mutation_aspect标题的边界框,在绘制标题时显然保持不变.虽然它mutation_aspect本身基本上只改变了盒子的高度,但是可以使用非常大的填充物来设置盒子,并设置mutation_aspect为非常小的数量,使得盒子的末端看起来宽度变宽.此解决方案的明显缺点是,填充和方面的值必须通过反复试验找到,并且将针对不同的字体和图形大小进行更改.在我的情况下,值mutation_aspect = 0.04和pad=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()
Run Code Online (Sandbox Code Playgroud)
Vla*_*lov 13
您可以在主要文本上方创建辅助轴,并将其用作标题的"框",而不是缩放标题文本本身的边界框.由于轴通常看起来不像方框,我们将关闭其轴标签和刻度,并将背景颜色设置为黑色以匹配OP.
我用同样的方法进行辅助,配套,轴作为这里.
另外,我习惯AnchoredText将标题文本捕捉到轴,以便它可以很容易地位于它的中心.
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText
from mpl_toolkits.axes_grid1 import make_axes_locatable
import pandas as pd
import numpy as np
s = pd.Series(np.random.lognormal(.001, .01, 100))
ax = s.cumprod().plot()
divider = make_axes_locatable(ax)
cax = divider.append_axes("top", size="11%", pad=0)
cax.get_xaxis().set_visible(False)
cax.get_yaxis().set_visible(False)
cax.set_facecolor('black')
at = AnchoredText("My Log Normal Example", loc=10,
prop=dict(backgroundcolor='black',
size=12, color='white'))
cax.add_artist(at)
plt.show()
Run Code Online (Sandbox Code Playgroud)
编辑:对于旧matplotlib版本,您可能需要cax.set_axis_bgcolor('black')在设置背景颜色时切换到.
| 归档时间: |
|
| 查看次数: |
3615 次 |
| 最近记录: |