【问题标题】:Seaborn distplot errors when generating histograms for single-element series为单元素系列生成直方图时出现 Seaborn distplot 错误
【发布时间】:2017-02-22 23:13:27
【问题描述】:

当我使用 seaborn 的 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

在查了一下源之后,我发现我可以通过指定 bin 的数量来避免这个错误。但这让我看到了另一个:

---------------------------------------------------------------------------
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

这里发生了什么?我可以使用一些解决方法来强制 seaborn 为这个单元素系列绘制直方图吗?对于上下文,我需要这个,因为我在一个共享轴上绘制多个直方图,描述不同的条件。在某些情况下,这种情况下可能只有一个元素,但我应该能够只绘制一个条形图!

【问题讨论】:

  • 我认为array([ 10.37823942]) 是一个单元素系列。此外,tmp = np.random.normal(10, 1, 1); assert tmp is np.atleast_1d(tmp) 运行没有错误,表明np.atleast_1d 返回相同的对象。
  • 另外,关于 numpy 中的标量主题,请注意 tmp 具有 shape(1,)len1。我可以用np.asscalar 转换为一个真正的标量——以证明 numpy 做出了这种区分——它不再具有形状或长度。
  • 是的,你是对的。

标签: python plot seaborn


【解决方案1】:

当数组长度为 1 时,您可以通过复制值来欺骗 seaborn

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 提供的好东西(其中大多数对单个元素没有意义),只需使用 matplotlib 或 pandas:

plt.hist(x, bins=1)

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

【讨论】:

  • 不错的解决方法。不幸的是,这意味着我必须标准化,或者接受双倍的计数。在我的情况下,一个相关的解决方法是限制条形的范围(例如bars=range(0, max_value, bin_size)),然后在数据集中添加一个元素,比如max_value+1。不过,我仍然很想找到一个直接的解决方案。
  • 请注意,我在循环中多次调用distplot,以在同一轴上绘制一组重叠的直方图,涵盖各种条件。我在这些图中使用了 seaborn 的功能,但需要能够绘制单个元素系列,因为在某些图中,其中一个条件将只有一个元素。此外,此用例排除了规范化。
  • 如果您不绘制 KDE(因此不使用规范化)并指定 bin 大小(因此不使用参考规则默认值),那么 sns.distplot 和 @ 之间没有功能差异987654335@.
  • @ohruunuruus 我不明白这个问题。您发布了一些不起作用的代码。如果它有效,我希望它能够创建一个像我的第一个(模数风格)一样的情节。我不是你所期望的,请澄清。另外两个是根据您的实际需要可能会或可能不会为您工作的替代方案,这对我来说是未知的。根据您提供的信息,我可以做到这一点。
  • @Goyo 和@mwaskom 你是对的,plt.hist() 在这种情况下实际上就足够了。我对您的sns.distplot() 解决方案的问题是它涉及数据的规范化,这在我的用例中是不可接受的。但是plt.hist() 可以开箱即用地处理我的输入。尽管如此,sns.distplot() 不能与单元素系列一起操作仍然非常令人不满意——恕我直言,这是一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多