yoa*_*ram 16 python matplotlib
已解决 - 请参阅以下关于组合wraptext.wrap和评论的评论plt.tightlayout.
问题:这是代码:
import matplotlib.pyplot as plt
plt.bar([1,2],[5,4])
plt.title('this is a very long title and therefore it gets cropped which is an unthinkable behaviour as it loses the information in the title')
plt.show()
Run Code Online (Sandbox Code Playgroud)
这创造了一个看起来像的人物 
标题被裁剪,如何让它显示整个标题?
更新:我正在寻找一种解决方案,使图形大小与标题和轴标签中的文本相匹配,而不是用于使用换行符切割标题的解决方案,因为这种解决方案并不总是有用:
from textwrap import wrap
import matplotlib.pyplot as plt
title = 'this is a very long title and therefore it gets cropped which is an unthinkable behaviour as it loses the information in the title'*5
plt.bar([1,2],[5,4])
plt.title('\n'.join(wrap(title,60)))
plt.show()`
Run Code Online (Sandbox Code Playgroud)
看结果: 
ami*_*des 18
您可以尝试这里找到的解决方案.
这是相当多的代码,但它似乎处理文本包装上的任何类型的文本.
以下是解决方案中的代码,经过修改以适合您的示例:
import matplotlib.pyplot as plt
def main():
fig = plt.figure()
plt.subplots_adjust(top=0.85) # use a lower number to make more vertical space
plt.bar([1,2],[5,4])
fig.canvas.mpl_connect('draw_event', on_draw)
plt.title('this is a very long title and therefore it gets cropped which is an unthinkable behaviour as it loses the information in the title')
plt.savefig('./test.png')
def on_draw(event):
"""Auto-wraps all text objects in a figure at draw-time"""
import matplotlib as mpl
fig = event.canvas.figure
# Cycle through all artists in all the axes in the figure
for ax in fig.axes:
for artist in ax.get_children():
# If it's a text artist, wrap it...
if isinstance(artist, mpl.text.Text):
autowrap_text(artist, event.renderer)
# Temporarily disconnect any callbacks to the draw event...
# (To avoid recursion)
func_handles = fig.canvas.callbacks.callbacks[event.name]
fig.canvas.callbacks.callbacks[event.name] = {}
# Re-draw the figure..
fig.canvas.draw()
# Reset the draw event callbacks
fig.canvas.callbacks.callbacks[event.name] = func_handles
def autowrap_text(textobj, renderer):
"""Wraps the given matplotlib text object so that it exceed the boundaries
of the axis it is plotted in."""
import textwrap
# Get the starting position of the text in pixels...
x0, y0 = textobj.get_transform().transform(textobj.get_position())
# Get the extents of the current axis in pixels...
clip = textobj.get_axes().get_window_extent()
# Set the text to rotate about the left edge (doesn't make sense otherwise)
textobj.set_rotation_mode('anchor')
# Get the amount of space in the direction of rotation to the left and
# right of x0, y0 (left and right are relative to the rotation, as well)
rotation = textobj.get_rotation()
right_space = min_dist_inside((x0, y0), rotation, clip)
left_space = min_dist_inside((x0, y0), rotation - 180, clip)
# Use either the left or right distance depending on the horiz alignment.
alignment = textobj.get_horizontalalignment()
if alignment is 'left':
new_width = right_space
elif alignment is 'right':
new_width = left_space
else:
new_width = 2 * min(left_space, right_space)
# Estimate the width of the new size in characters...
aspect_ratio = 0.5 # This varies with the font!!
fontsize = textobj.get_size()
pixels_per_char = aspect_ratio * renderer.points_to_pixels(fontsize)
# If wrap_width is < 1, just make it 1 character
wrap_width = max(1, new_width // pixels_per_char)
try:
wrapped_text = textwrap.fill(textobj.get_text(), wrap_width)
except TypeError:
# This appears to be a single word
wrapped_text = textobj.get_text()
textobj.set_text(wrapped_text)
def min_dist_inside(point, rotation, box):
"""Gets the space in a given direction from "point" to the boundaries of
"box" (where box is an object with x0, y0, x1, & y1 attributes, point is a
tuple of x,y, and rotation is the angle in degrees)"""
from math import sin, cos, radians
x0, y0 = point
rotation = radians(rotation)
distances = []
threshold = 0.0001
if cos(rotation) > threshold:
# Intersects the right axis
distances.append((box.x1 - x0) / cos(rotation))
if cos(rotation) < -threshold:
# Intersects the left axis
distances.append((box.x0 - x0) / cos(rotation))
if sin(rotation) > threshold:
# Intersects the top axis
distances.append((box.y1 - y0) / sin(rotation))
if sin(rotation) < -threshold:
# Intersects the bottom axis
distances.append((box.y0 - y0) / sin(rotation))
return min(distances)
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
这会产生以下情节:

更新:
使用以下行在图的顶部和实际绘图的顶部之间创建更多空间:
plt.subplots_adjust(top=0.85) # use a lower number to make more vertical space
Run Code Online (Sandbox Code Playgroud)
例如,如果您使用:
plt.subplots_adjust(top=0.5)
Run Code Online (Sandbox Code Playgroud)
输出结果如下:

Ale*_*x L 13
您可以\n使用textwrap自动用换行符()包装文本:
>>> longstring = "this is a very long title and therefore it gets cropped which is an unthinkable behaviour as it loses the information in the title"
>>> "\n".join(textwrap.wrap(longstring, 100))
'this is a very long title and therefore it gets cropped which is an unthinkable behaviour as it\nloses the information in the title'
Run Code Online (Sandbox Code Playgroud)
在这种情况下,100是每行的字符数(到最近的空格 - textwrap尝试不分解单词)
另一种选择是减小字体的大小:
matplotlib.rcParams.update({'font.size': 12})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17311 次 |
| 最近记录: |