2015-04-30 41 views
4

在Seaborn中,您可以使用FacetGrid来设置要绘制的数据感知网格。然后,您可以使用mapmap_dataframe方法绘制到这些网格。Seaborn FacetGrid用户定义的绘图功能

我无法正确指定与mapmap_dataframe一起使用的用户定义绘图函数。在这个例子中,我使用errorbar函数,我想将错误值传递为2xN数组。在我的例子中(来自@ mwaskom的回答here)错误是对称的 - 但想象我有一种情况,他们不是。

In [255]: 

from scipy import stats 
tips_all = sns.load_dataset("tips") 
tips_grouped = tips_all.groupby(["smoker", "size"]) 
tips = tips_grouped.mean() 
tips["error_min"] = tips_grouped.total_bill.apply(stats.sem) * 1.96 
tips["error_max"] = tips_grouped.total_bill.apply(stats.sem) * 1.96 
tips.reset_index(inplace=True) 
tips 

Out[255]: 
    smoker size total_bill tip  error_min error_max 
0 No 1 8.660000 1.415000 2.763600 2.763600 
1 No 2 15.342333 2.489000 0.919042 0.919042 
2 No 3 21.009615 3.069231 2.680447 2.680447 
3 No 4 27.769231 4.195769 3.303131 3.303131 
4 No 5 30.576667 5.046667 11.620808 11.620808 
5 No 6 34.830000 5.225000 9.194360 9.194360 
6 Yes  1 5.825000 1.460000 5.399800 5.399800 
7 Yes  2 17.955758 2.709545 1.805528 1.805528 
8 Yes  3 28.191667 4.095000 6.898186 6.898186 
9 Yes  4 30.609091 3.992727 5.150063 5.150063 
10 Yes  5 29.305000 2.500000 2.263800 2.263800 

定义我的错误栏的功能,这需要数据和索引错误列产生2×N个排列:

In [256]: 
def my_errorbar(*args, **kwargs): 
    data = kwargs['data'] 
    errors = np.vstack([data['error_min'], 
         data['error_max']]) 
    print(errors) 
    plt.errorbar(data[args[0]], 
       data[args[1]], 
       yerr=errors, 
       **kwargs); 

使用map_dataframe调用(因为我的函数获取的数据作为kwarg):

In [257]: 

g = sns.FacetGrid(tips, col="smoker", size=5) 
g.map_dataframe(my_errorbar, "size", "total_bill", marker="o") 

[[ 2.7636  0.9190424 2.68044722 3.30313068 11.62080751 
    9.19436049] 
[ 2.7636  0.9190424 2.68044722 3.30313068 11.62080751 
    9.19436049]] 

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-257-dc8b35ec70ec> in <module>() 
     1 g = sns.FacetGrid(tips, col="smoker", size=5) 
----> 2 g.map_dataframe(my_errorbar, "size", "total_bill", marker="o") 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/seaborn/axisgrid.py in map_dataframe(self, func, *args, **kwargs) 
    509 
    510    # Draw the plot 
--> 511    self._facet_plot(func, ax, args, kwargs) 
    512 
    513   # Finalize the annotations and layout 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/seaborn/axisgrid.py in _facet_plot(self, func, ax, plot_args, plot_kwargs) 
    527 
    528   # Draw the plot 
--> 529   func(*plot_args, **plot_kwargs) 
    530 
    531   # Sort out the supporting information 

<ipython-input-256-62202c841233> in my_errorbar(*args, **kwargs) 
     9     data[args[1]], 
    10     yerr=errors, 
---> 11     **kwargs);  
    12 
    13 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/pyplot.py in errorbar(x, y, yerr, xerr, fmt, ecolor, elinewidth, capsize, barsabove, lolims, uplims, xlolims, xuplims, errorevery, capthick, hold, **kwargs) 
    2764       barsabove=barsabove, lolims=lolims, uplims=uplims, 
    2765       xlolims=xlolims, xuplims=xuplims, 
-> 2766       errorevery=errorevery, capthick=capthick, **kwargs) 
    2767   draw_if_interactive() 
    2768  finally: 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/axes/_axes.py in errorbar(self, x, y, yerr, xerr, fmt, ecolor, elinewidth, capsize, barsabove, lolims, uplims, xlolims, xuplims, errorevery, capthick, **kwargs) 
    2859 
    2860   if not barsabove and plot_line: 
-> 2861    l0, = self.plot(x, y, fmt, **kwargs) 
    2862 
    2863   if ecolor is None: 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/axes/_axes.py in plot(self, *args, **kwargs) 
    1371   lines = [] 
    1372 
-> 1373   for line in self._get_lines(*args, **kwargs): 
    1374    self.add_line(line) 
    1375    lines.append(line) 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/axes/_base.py in _grab_next_args(self, *args, **kwargs) 
    302     return 
    303    if len(remaining) <= 3: 
--> 304     for seg in self._plot_args(remaining, kwargs): 
    305      yield seg 
    306     return 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/axes/_base.py in _plot_args(self, tup, kwargs) 
    290   ncx, ncy = x.shape[1], y.shape[1] 
    291   for j in xrange(max(ncx, ncy)): 
--> 292    seg = func(x[:, j % ncx], y[:, j % ncy], kw, kwargs) 
    293    ret.append(seg) 
    294   return ret 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/axes/_base.py in _makeline(self, x, y, kw, kwargs) 
    242        **kw 
    243       ) 
--> 244   self.set_lineprops(seg, **kwargs) 
    245   return seg 
    246 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/axes/_base.py in set_lineprops(self, line, **kwargs) 
    184     raise TypeError('There is no line property "%s"' % key) 
    185    func = getattr(line, funcName) 
--> 186    func(val) 
    187 
    188  def set_patchprops(self, fill_poly, **kwargs): 

/Users/x/miniconda3/envs/default/lib/python3.4/site-packages/matplotlib/lines.py in set_data(self, *args) 
    557   """ 
    558   if len(args) == 1: 
--> 559    x, y = args[0] 
    560   else: 
    561    x, y = args 

ValueError: too many values to unpack (expected 2) 

我不明白在这里失败的原因。请注意,绘图函数获得的东西,因为会生成第一个网格的误差线图。我假设我没有正确传递**kwargs字典。

一般来说,如果tutorial for Seaborn包含一个或两个传递给mapmap_dataframe的用户定义绘图函数示例,我会发现它非常有帮助。

+1

我不是确切地确定你的问题是什么,但我认为'data'将会作为'** kwargs'的一部分传递给'plt.errorbar'。根据堆栈跟踪,可能是这个问题;你可以尝试弹出它或者将它作为一个明确的参数来试图避免这种情况。 – mwaskom

+0

感谢@mwaskom,这表示感谢。魔术一如既往。 – tsawallis

回答

3

这是@ mwaskom的答案,和工作的治疗(见注释):

只要改变my_errorbar功能,使其弹出的data出来的关键词字典的:

def my_errorbar(*args, **kwargs): 
    data = kwargs.pop('data') 
    errors = np.vstack([data['error_min'], 
         data['error_max']]) 

    print(errors) 

    plt.errorbar(data[args[0]], 
       data[args[1]], 
       yerr=errors, 
       **kwargs);  
相关问题