Seaborn countplot 为 x 值设置图例 [英] Seaborn countplot set legend for x values

查看:119
本文介绍了Seaborn countplot 为 x 值设置图例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆