Python 如何在matplotlib图例中添加字符串作为艺术家?
我试图在python图形中创建一个图例,其中艺术家是一个字符串(一个字母),然后标记该字符串。例如,我想要下图的图例:Python 如何在matplotlib图例中添加字符串作为艺术家?,python,matplotlib,legend,legend-properties,Python,Matplotlib,Legend,Legend Properties,我试图在python图形中创建一个图例,其中艺术家是一个字符串(一个字母),然后标记该字符串。例如,我想要下图的图例: import numpy as np import matplotlib.pyplot as plt import string N = 7 x = np.random.rand(N) y = np.random.rand(N) colors = np.random.rand(N) area = np.pi * (15 * np.random.rand(N))**2 pl
import numpy as np
import matplotlib.pyplot as plt
import string
N = 7
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
for i,j in enumerate(zip(x,y)):
plt.annotate(list(string.ascii_uppercase)[i],xy=j)
plt.show()
这里的传说是这样的:
A-型号名称A
B-型号名称B
C-型号名称C
D-型号名称D
等等等等
我不知道该怎么做的是放置“A”、“B”。。。。作为传奇文本的艺术家。我可以看到你会如何使用线或补丁,或类似的东西。但是一般来说,有没有一种方法可以使用字符串作为艺术家,而不是线呢?我认为没有文本的图例处理程序(请参阅可用的图例处理程序列表)。但是你可以实现你自己的。在这里,我将修改上面链接中的示例:
import matplotlib.pyplot as plt
import matplotlib.text as mpl_text
class AnyObject(object):
def __init__(self, text, color):
self.my_text = text
self.my_color = color
class AnyObjectHandler(object):
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
print orig_handle
x0, y0 = handlebox.xdescent, handlebox.ydescent
width, height = handlebox.width, handlebox.height
patch = mpl_text.Text(x=0, y=0, text=orig_handle.my_text, color=orig_handle.my_color, verticalalignment=u'baseline',
horizontalalignment=u'left', multialignment=None,
fontproperties=None, rotation=45, linespacing=None,
rotation_mode=None)
handlebox.add_artist(patch)
return patch
obj_0 = AnyObject("A", "purple")
obj_1 = AnyObject("B", "green")
plt.legend([obj_0, obj_1], ['Model Name A', 'Model Name B'],
handler_map={obj_0:AnyObjectHandler(), obj_1:AnyObjectHandler()})
plt.show()
我认为没有文本的图例处理程序(请参阅可用的图例处理程序列表)。但是你可以实现你自己的。在这里,我将修改上面链接中的示例:
import matplotlib.pyplot as plt
import matplotlib.text as mpl_text
class AnyObject(object):
def __init__(self, text, color):
self.my_text = text
self.my_color = color
class AnyObjectHandler(object):
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
print orig_handle
x0, y0 = handlebox.xdescent, handlebox.ydescent
width, height = handlebox.width, handlebox.height
patch = mpl_text.Text(x=0, y=0, text=orig_handle.my_text, color=orig_handle.my_color, verticalalignment=u'baseline',
horizontalalignment=u'left', multialignment=None,
fontproperties=None, rotation=45, linespacing=None,
rotation_mode=None)
handlebox.add_artist(patch)
return patch
obj_0 = AnyObject("A", "purple")
obj_1 = AnyObject("B", "green")
plt.legend([obj_0, obj_1], ['Model Name A', 'Model Name B'],
handler_map={obj_0:AnyObjectHandler(), obj_1:AnyObjectHandler()})
plt.show()
解决方案将取决于轴中是否已经有文本也应该出现在图例中,或者这些文本是否独立于轴中的任何内容 A.现有文本或注释 如果轴中已有文本或注释,则可以将它们作为图例的句柄提供。注册到
Legend
类的新TextHandlerA
将这些Text
s作为输入。与往常一样,通过label
参数从艺术家那里获取相应的标签
import numpy as np
import matplotlib.pyplot as plt
import string
from matplotlib.legend_handler import HandlerBase
from matplotlib.text import Text, Annotation
from matplotlib.legend import Legend
class TextHandlerA(HandlerBase):
def create_artists(self, legend, artist ,xdescent, ydescent,
width, height, fontsize, trans):
tx = Text(width/2.,height/2, artist.get_text(), fontsize=fontsize,
ha="center", va="center", fontweight="bold")
return [tx]
Legend.update_default_handler_map({Text : TextHandlerA()})
N = 7
x = np.random.rand(N)*.7
y = np.random.rand(N)*.7
colors = np.random.rand(N)
handles = list(string.ascii_uppercase)
labels = [f"Model Name {c}" for c in handles]
fig, ax = plt.subplots()
ax.scatter(x, y, s=100, c=colors, alpha=0.5)
for i, xy in enumerate(zip(x, y)):
ax.annotate(handles[i], xy=xy, label= labels[i])
ax.legend(handles=ax.texts)
plt.show()
B.字符串列表中的图例。
如果希望图例条目本身不是轴中的文本,可以从字符串列表中创建它们。在这种情况下,TextHandlerB
将字符串作为输入。在这种情况下,需要使用两个字符串列表调用图例,一个用于句柄,一个用于标签
import numpy as np
import matplotlib.pyplot as plt
import string
from matplotlib.legend_handler import HandlerBase
from matplotlib.text import Text
from matplotlib.legend import Legend
class TextHandlerB(HandlerBase):
def create_artists(self, legend, text ,xdescent, ydescent,
width, height, fontsize, trans):
tx = Text(width/2.,height/2, text, fontsize=fontsize,
ha="center", va="center", fontweight="bold")
return [tx]
Legend.update_default_handler_map({str : TextHandlerB()})
N = 7
x = np.random.rand(N)*.7
y = np.random.rand(N)*.7
colors = np.random.rand(N)
handles = list(string.ascii_uppercase)[:N]
labels = [f"Model Name {c}" for c in handles]
fig, ax = plt.subplots()
ax.scatter(x, y, s=100, c=colors, alpha=0.5)
for i, xy in enumerate(zip(x, y)):
ax.annotate(handles[i], xy=xy)
ax.legend(handles=handles, labels=labels)
plt.show()
在这两种情况下,输出都是
解决方案将取决于轴中是否已经有文本也应该出现在图例中,或者这些文本是否独立于轴中的任何内容 A.现有文本或注释 如果轴中已有文本或注释,则可以将它们作为图例的句柄提供。注册到
Legend
类的新TextHandlerA
将这些Text
s作为输入。与往常一样,通过label
参数从艺术家那里获取相应的标签
import numpy as np
import matplotlib.pyplot as plt
import string
from matplotlib.legend_handler import HandlerBase
from matplotlib.text import Text, Annotation
from matplotlib.legend import Legend
class TextHandlerA(HandlerBase):
def create_artists(self, legend, artist ,xdescent, ydescent,
width, height, fontsize, trans):
tx = Text(width/2.,height/2, artist.get_text(), fontsize=fontsize,
ha="center", va="center", fontweight="bold")
return [tx]
Legend.update_default_handler_map({Text : TextHandlerA()})
N = 7
x = np.random.rand(N)*.7
y = np.random.rand(N)*.7
colors = np.random.rand(N)
handles = list(string.ascii_uppercase)
labels = [f"Model Name {c}" for c in handles]
fig, ax = plt.subplots()
ax.scatter(x, y, s=100, c=colors, alpha=0.5)
for i, xy in enumerate(zip(x, y)):
ax.annotate(handles[i], xy=xy, label= labels[i])
ax.legend(handles=ax.texts)
plt.show()
B.字符串列表中的图例。
如果希望图例条目本身不是轴中的文本,可以从字符串列表中创建它们。在这种情况下,TextHandlerB
将字符串作为输入。在这种情况下,需要使用两个字符串列表调用图例,一个用于句柄,一个用于标签
import numpy as np
import matplotlib.pyplot as plt
import string
from matplotlib.legend_handler import HandlerBase
from matplotlib.text import Text
from matplotlib.legend import Legend
class TextHandlerB(HandlerBase):
def create_artists(self, legend, text ,xdescent, ydescent,
width, height, fontsize, trans):
tx = Text(width/2.,height/2, text, fontsize=fontsize,
ha="center", va="center", fontweight="bold")
return [tx]
Legend.update_default_handler_map({str : TextHandlerB()})
N = 7
x = np.random.rand(N)*.7
y = np.random.rand(N)*.7
colors = np.random.rand(N)
handles = list(string.ascii_uppercase)[:N]
labels = [f"Model Name {c}" for c in handles]
fig, ax = plt.subplots()
ax.scatter(x, y, s=100, c=colors, alpha=0.5)
for i, xy in enumerate(zip(x, y)):
ax.annotate(handles[i], xy=xy)
ax.legend(handles=handles, labels=labels)
plt.show()
在这两种情况下,输出都是
谢谢您的回复。当我运行上面的代码时,我得到了:“TypeError:‘AnyObjectHandler’对象不可调用。”有什么建议吗?是什么原因造成的?@SeanElvidge:我的第一个猜测是你有一个打字错误。。至少当这种事情发生时,这是通常的结果。我正在运行mpl版本1.4.0。我将再次剪切并粘贴我的工作代码,以防出错。我正在运行mpl版本1.3.1。我刚刚更新到1.4.2并运行了您的代码,它工作得非常好!非常感谢。我已经玩了几天你的示例代码,想不出/找不到一个好方法来修改它以接受多个(不同的)艺术家和标签。至少在没有定义我想要的“AnyObjectHandler”的情况下是这样(因为对象中的“文本”是硬编码的,如果我尝试将其作为关键字,函数将停止工作)。你能为“a型a”,“B型B”提供一个制作图例的方法吗?非常感谢您(持续)的帮助。传递给句柄的
源句柄
就是要处理的对象。也就是说,处理程序可以从对象获取信息,并使用该信息构建符号。我已经更新了我的示例,使其包含了一些对象(尽管我还将再次更新以更改颜色)。感谢您的回复。当我运行上面的代码时,我得到了:“TypeError:‘AnyObjectHandler’对象不可调用。”有什么建议吗?是什么原因造成的?@SeanElvidge:我的第一个猜测是你有一个打字错误。。至少当这种事情发生时,这是通常的结果。我正在运行mpl版本1.4.0。我将再次剪切并粘贴我的工作代码,以防出错。我正在运行mpl版本1.3.1。我刚刚更新到1.4.2并运行了您的代码,它工作得非常好!非常感谢。我已经玩了几天你的示例代码,想不出/找不到一个好方法来修改它以接受多个(不同的)艺术家和标签。至少在没有定义我想要的“AnyObjectHandler”的情况下是这样(因为对象中的“文本”是硬编码的,如果我尝试将其作为关键字,函数将停止工作)。你能为“a型a”,“B型B”提供一个制作图例的方法吗?非常感谢您(持续)的帮助。传递给句柄的源句柄
就是要处理的对象。也就是说,处理程序可以从对象获取信息,并使用该信息构建符号。我已经更新了我的示例,使其包含一些对象(尽管我还将再次更新以更改颜色)。