2015-04-30 3 views
4

В Seaborn вы можете использовать FacetGrid для настройки сетей с поддержкой данных, на которых можно построить график. Затем вы можете использовать методы map или map_dataframe для построения этих сеток.Функция определения местоположения Seaborn FacetGrid, заданная пользователем

У меня возникли проблемы с правильным определением пользовательской функции графика, которая работает с map или map_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 

Определите свою функцию бара ошибки, которая принимает данные и индексы столбцов ошибок для создания массива 2XN:

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 содержал один или два примера пользовательских функций графика, переданных map или map_dataframe.

+1

Я не точно знаю, какова ваша проблема, но я думаю, что 'data' будет передаваться в' plt.errorbar' как часть '** kwargs'. Основываясь на трассировке стека, возможно, это проблема; вы можете попытаться поскользнуться или сделать это явным аргументом, чтобы попытаться избежать этого. – 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);  
Смежные вопросы