Seaborn countplot 为 x 值设置图例 [英] Seaborn countplot set legend for x values
问题描述
我正在通过 sns.countplot()
我正尝试向图中添加x值的图例:句柄是x值的集合,标签是x值的描述.
ax = sns.countplot(x = df.GARAGE_DOM)句柄,标签= ax.get_legend_handles_labels()句柄= ["VP","BC","GC","GP","JC","PO"]标签 = [Voie Publique"、box"、Garage couvert"、garage particulier clos"、Jardin clos"、parking ouvert"]by_label = OrderedDict(zip(句柄,标签))ax.legend(by_label.keys(), by_label.values())
但是,我得到警告
<块引用>用户警告:
图例不支持VP"实例.可以使用代理艺术家来代替.请参阅:
感谢您的帮助.
这里是一种可能的解决方案,将文本字段创建为图例处理程序.下面将创建一个 TextHandler
用于创建图例艺术家,它是一个简单的 matplotlib.text.Text
实例.图例的句柄作为(文本,颜色)的元组给出,TextHandler
从中创建所需的 Text
.
导入 seaborn 为 sns导入matplotlib.pyplot作为plt从 matplotlib.legend_handler 导入 HandlerBase从matplotlib.text导入文本将numpy导入为np将熊猫作为pd导入类 TextHandler(HandlerBase):def create_artists(self,legend,tup,xdescent,ydescent,宽度,高度,字体大小,反式):tx =文字(宽度/2.,高度/2,tup [0],fontsize = fontsize,ha="center", va="center", color=tup[1], fontweight="bold")返回 [tx]a = np.random.choice(["VP", "BC", "GC", "GP", "JC", "PO"], size=100,p=np.arange(1,7)/21.)df = pd.DataFrame(a,columns = ["GARAGE_DOM"])ax = sns.countplot(x = df.GARAGE_DOM)handltext = ["VP", "BC", "GC", "GP", "JC", "PO"]标签 = ["Voie Publique", "box", "Garage couvert", "garage particulier clos", "Jardin clos", "parking ouvert"]t = ax.get_xticklabels()labeldic = dict(zip(handltext,标签))标签= [t中的h的labeldic [h.get_text()]句柄= [[(h.get_text(),c.get_fc())对于zip(t,ax.patches)中的h,cax.legend(handles, labels, handler_map={tuple : TextHandler()})plt.show()
<小时>上面的解决方案是下面原始版本的更新版本,似乎更复杂.以下是原始解决方案,该解决方案使用 TextArea
和 AnchoredOffsetbox
将文本放置在图例中.
将seaborn.apionly导入为sns导入matplotlib.pyplot作为plt导入matplotlib.patches作为补丁从matplotlib.offsetbox导入TextArea,AnchoredOffsetbox从matplotlib.transforms导入TransformedBbox,Bbox从 matplotlib.legend_handler 导入 HandlerBase将numpy导入为np将熊猫作为pd导入类TextHandler(HandlerBase):def __init __(self,text,color ="k"):self.text =文字self.color =颜色super(TextHandler, self).__init__()def create_artists(self,legend, orig_handle,xdescent, ydescent,宽度,高度,字体大小,trans):bb = Bbox.from_bounds(xdescent,ydescent,width,height)tbb = TransformedBbox(bb,trans)textbox = TextArea(self.text,textprops = {"weight":"bold","color":self.color})ab = AnchoredOffsetbox(loc=10,child=textbox, bbox_to_anchor=tbb, frameon=False)返回 [ab]a = np.random.choice(["VP","BC","GC","GP","JC","PO"],大小= 100,p = np.arange(1,7)/21.)df = pd.DataFrame(a,columns = ["GARAGE_DOM"])ax = sns.countplot(x = df.GARAGE_DOM)handltext = ["VP","BC","GC","GP","JC","PO"]标签 = ["Voie Publique", "box", "Garage couvert", "garage particulier clos", "Jardin clos", "parking ouvert"]handles = [手写文字中h的patchs.Rectangle((0,0),1,1)t = ax.get_xticklabels()labeldic = dict(zip(handltext,标签))标签 = [labeldic[h.get_text()] for h in t]handlers = [TextHandler(h.get_text(),c.get_fc()) for h,c in zip(t,ax.patches)]handlermap = dict(zip(句柄,处理程序))ax.legend(句柄,标签,handler_map = handlermap,)plt.show()
<小时>
另见这个更通用的答案
I'm ploting a categorical data and value count by sns.countplot()
I'm trying to add legend for x-values to the figure as following: handles is set of x-value, labels is the descriptions of x-values.
ax = sns.countplot(x = df.GARAGE_DOM)
handles, labels = ax.get_legend_handles_labels()
handles = ["VP", "BC", "GC", "GP", "JC", "PO"]
labels = ["Voie Publique", "box", "Garage couvert", "garage particulier clos", "Jardin clos", "parking ouvert"]
by_label = OrderedDict(zip(handles,labels))
ax.legend(by_label.keys(), by_label.values())
However, I got warning that
UserWarning:
Legend does not support 'VP' instances. A proxy artist may be used instead. See: http://matplotlib.org/users/legend_guide.html#using-proxy-artist
I've read the doc of proxy artist but I didn't find examples in my case.
Thanks for your help.
Here is a possible solution, creating a text field as a legend handler.
The following would create a TextHandler
to be used to create the legend artist, which is a simple matplotlib.text.Text
instance. The handles for the legend are given as tuples of (text, color) from which the TextHandler
creates the desired Text
.
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerBase
from matplotlib.text import Text
import numpy as np
import pandas as pd
class TextHandler(HandlerBase):
def create_artists(self, legend, tup ,xdescent, ydescent,
width, height, fontsize,trans):
tx = Text(width/2.,height/2,tup[0], fontsize=fontsize,
ha="center", va="center", color=tup[1], fontweight="bold")
return [tx]
a = np.random.choice(["VP", "BC", "GC", "GP", "JC", "PO"], size=100,
p=np.arange(1,7)/21. )
df = pd.DataFrame(a, columns=["GARAGE_DOM"])
ax = sns.countplot(x = df.GARAGE_DOM)
handltext = ["VP", "BC", "GC", "GP", "JC", "PO"]
labels = ["Voie Publique", "box", "Garage couvert", "garage particulier clos", "Jardin clos", "parking ouvert"]
t = ax.get_xticklabels()
labeldic = dict(zip(handltext, labels))
labels = [labeldic[h.get_text()] for h in t]
handles = [(h.get_text(),c.get_fc()) for h,c in zip(t,ax.patches)]
ax.legend(handles, labels, handler_map={tuple : TextHandler()})
plt.show()
The above solution is an updated version of the original version below, which seems more complicated. The following is the original solution, which uses a
TextArea
and an AnchoredOffsetbox
to place the text inside the legend.import seaborn.apionly as sns
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.offsetbox import TextArea, AnchoredOffsetbox
from matplotlib.transforms import TransformedBbox, Bbox
from matplotlib.legend_handler import HandlerBase
import numpy as np
import pandas as pd
class TextHandler(HandlerBase):
def __init__(self, text, color="k"):
self.text = text
self.color = color
super(TextHandler, self).__init__()
def create_artists(self, legend, orig_handle,xdescent, ydescent,
width, height, fontsize,trans):
bb = Bbox.from_bounds(xdescent,ydescent, width,height)
tbb = TransformedBbox(bb, trans)
textbox = TextArea(self.text, textprops={"weight":"bold","color":self.color})
ab = AnchoredOffsetbox(loc=10,child=textbox, bbox_to_anchor=tbb, frameon=False)
return [ab]
a = np.random.choice(["VP", "BC", "GC", "GP", "JC", "PO"], size=100,
p=np.arange(1,7)/21. )
df = pd.DataFrame(a, columns=["GARAGE_DOM"])
ax = sns.countplot(x = df.GARAGE_DOM)
handltext = ["VP", "BC", "GC", "GP", "JC", "PO"]
labels = ["Voie Publique", "box", "Garage couvert", "garage particulier clos", "Jardin clos", "parking ouvert"]
handles = [ patches.Rectangle((0,0),1,1) for h in handltext]
t = ax.get_xticklabels()
labeldic = dict(zip(handltext, labels))
labels = [labeldic[h.get_text()] for h in t]
handlers = [TextHandler(h.get_text(),c.get_fc()) for h,c in zip(t,ax.patches)]
handlermap = dict(zip(handles, handlers))
ax.legend(handles, labels, handler_map=handlermap,)
plt.show()
Also see this more generic answer
这篇关于Seaborn countplot 为 x 值设置图例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!