2017-02-22 10 views
3

Когда я использую морфологию distplot (в 0.7.1) для визуализации гистограммы, я получаю сообщение об ошибке, если входная серия содержит только один элемент. Другими словами, что-то вродеОшибки локализации морского судна при генерации гистограмм для одноэлементных серий

import numpy as np 
import seaborn as sns 

num_elements = 1000 
sns.distplot(np.random.normal(10, 1, num_elements)) 

прекрасно работает, но если я устанавливаю num_elements 1 я получаю следующее сообщение об ошибке:

In [8]: num_elements = 1 

In [9]: sns.distplot(np.random.normal(10, 1, num_elements)) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-9-35e3f8293582> in <module>() 
----> 1 sns.distplot(np.random.normal(10, 1, num_elements)) 

/usr/local/lib/python2.7/site-packages/seaborn/distributions.pyc in distplot(a, bins, hist, kde, rug, fit, hist_kws, kde_kws, rug_kws, fit_kws, color, vertical, norm_hist, axlabel, label, ax) 
    207  if hist: 
    208   if bins is None: 
--> 209    bins = min(_freedman_diaconis_bins(a), 50) 
    210   hist_kws.setdefault("alpha", 0.4) 
    211   hist_kws.setdefault("normed", norm_hist) 

/usr/local/lib/python2.7/site-packages/seaborn/distributions.pyc in _freedman_diaconis_bins(a) 
    28  # From http://stats.stackexchange.com/questions/798/ 
    29  a = np.asarray(a) 
---> 30  h = 2 * iqr(a)/(len(a) ** (1/3)) 
    31  # fall back to sqrt(a) bins if iqr is 0 
    32  if h == 0: 

TypeError: len() of unsized object 

После ковыряться источника немного, я обнаружил, что я мог бы избежать этого ошибка, указав количество ящиков. Но это открывает мне другое:

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-10-6e6569de737a> in <module>() 
----> 1 sns.distplot(np.random.normal(10, 1, num_elements), bins=10) 

/usr/local/lib/python2.7/site-packages/seaborn/distributions.pyc in distplot(a, bins, hist, kde, rug, fit, hist_kws, kde_kws, rug_kws, fit_kws, c\olor, vertical, norm_hist, axlabel, label, ax) 
    213   hist_color = hist_kws.pop("color", color) 
    214   ax.hist(a, bins, orientation=orientation, 
--> 215     color=hist_color, **hist_kws) 
    216   if hist_color != color: 
    217    hist_kws["color"] = hist_color 

/usr/local/lib/python2.7/site-packages/matplotlib/__init__.pyc in inner(ax, *args, **kwargs) 
    1817      warnings.warn(msg % (label_namer, func.__name__), 
    1818         RuntimeWarning, stacklevel=2) 
-> 1819    return func(ax, *args, **kwargs) 
    1820   pre_doc = inner.__doc__ 
    1821   if pre_doc is None: 

/usr/local/lib/python2.7/site-packages/matplotlib/axes/_axes.pyc in hist(self, x, bins, range, normed, weights, cumulative, bottom, histtype, align, orientation, rwidth, log, color, label, stacked, **kwargs) 
    5933    x = np.array([[]]) 
    5934   else: 
-> 5935    x = _normalize_input(x, 'x') 
    5936   nx = len(x) # number of datasets 
    5937 

/usr/local/lib/python2.7/site-packages/matplotlib/axes/_axes.pyc in _normalize_input(inp, ename) 
    5875     else: 
    5876      raise ValueError(
-> 5877       "{ename} must be 1D or 2D".format(ename=ename)) 
    5878     if inp.shape[1] < inp.shape[0]: 
    5879      warnings.warn(

ValueError: x must be 1D or 2D 

Что здесь происходит? Есть ли способ обхода, который я могу использовать, чтобы заставить морской замок построить гистограмму для этой серии элементов? Для контекста мне это нужно, потому что я рисую несколько гистограмм, описывающих разные условия, на общей оси. В некоторых случаях в этом состоянии может быть только один элемент, но я должен иметь возможность отображать только один бар!

+0

Я бы рассмотреть 'массив ([+10,37823942])', чтобы быть одной серии элементов. Кроме того, 'tmp = np.random.normal (10, 1, 1); assert tmp is np.atleast_1d (tmp) 'работает без ошибок, указывая, что этот' np.atleast_1d' возвращает тот же объект обратно. – ohruunuruus

+0

Также, по теме скаляров в numpy, обратите внимание, что 'tmp' имеет' shape' '(1,)' и 'len'' 1'. Я могу преобразовать в настоящий скаляр - чтобы продемонстрировать, что numpy делает это различие - с 'np.asscalar', который больше не имеет формы или длины. – ohruunuruus

+0

Да, вы правы. – mwaskom

ответ

2

Вы можете обмануть seaborn, когда длина массива 1, дублируя значение:

rs = np.random.RandomState(0) 
num_elements = 1 
x = rs.normal(10, 1, num_elements) 
sns.distplot(np.r_[x, x], kde=False, norm_hist=True) 

seaborn histogram

Или, если вам не нужны лакомства, предоставляемые Сиборн (большинство из них не иметь смысл для одного элемента) просто использовать Matplotlib или панд:

plt.hist(x, bins=1) 

enter image description here

pd.Series(x).hist(bins=1); 

enter image description here

+0

Хорошее обходное решение. К сожалению, это означает, что я должен нормализовать или принять удвоенное количество. Связанный обходной путь, который работает в моем случае, включает ограничение диапазона баров (например, «bar = range (0, max_value, bin_size)»), а затем добавление элемента к набору данных в, например 'max_value + 1'. Тем не менее, я все равно хотел бы найти прямое решение. – ohruunuruus

+0

Обратите внимание, что я делаю несколько вызовов 'distplot' в цикле, чтобы построить перекрывающийся набор гистограмм в одной и той же оси, охватывающий множество условий. Я использую черты морского обитателя на этих участках, но мне нужно иметь возможность строить одну серию элементов, потому что на некоторых рисунках одно из условий будет иметь только один элемент. Кроме того, этот прецедент исключает нормализацию. – ohruunuruus

+0

Если вы не рисуете KDE (и, следовательно, не используете нормализацию) и указываете размер бина (и, следовательно, не используете правило ссылки по умолчанию), то нет никакого функционального различия между 'sns.distplot' и' ax.hist'. – mwaskom

Смежные вопросы