Python的:如何使同样大小的* *垃圾桶的直方图(Python: how to make an

2019-08-01 09:48发布

我有一组数据,并希望利用它的直方图。 我需要的仓,以具有相同的尺寸 ,我的意思是,它们必须包含相同数量的对象,而不是等间隔的仓的更常见(numpy.histogram)的问题。 这自然会在箱宽度的开支,可以 - 和一般的意志 - 是不同的。

我将指定所需的箱数和数据集,获得箱回报边缘。

Example:
data = numpy.array([1., 1.2, 1.3, 2.0, 2.1, 2.12])
bins_edges = somefunc(data, nbins=3)
print(bins_edges)
>> [1.,1.3,2.1,2.12]

这样的二进制位都含有2分,但它们的宽度(0.3,0.8,0.02)是不同的。

有两个限制: - 如果一组数据是相同的,包含它们的bin可能会更大。 - 如果有N个数据,并请求中号箱,将有N / M二进制位加一如果N%M不为0。

这段代码是一些多余的内容我已经写了,这很好地工作了小数据集。 如果我有10个** 9 +点,并希望加快这一进程?

  1 import numpy as np
  2 
  3 def def_equbin(in_distr, binsize=None, bin_num=None):
  4 
  5     try:
  6 
  7         distr_size = len(in_distr)
  8 
  9         bin_size = distr_size / bin_num
 10         odd_bin_size = distr_size % bin_num
 11 
 12         args = in_distr.argsort()
 13 
 14         hist = np.zeros((bin_num, bin_size))
 15 
 16         for i in range(bin_num):
 17             hist[i, :] = in_distr[args[i * bin_size: (i + 1) * bin_size]]
 18 
 19         if odd_bin_size == 0:
 20             odd_bin = None
 21             bins_limits = np.arange(bin_num) * bin_size
 22             bins_limits = args[bins_limits]
 23             bins_limits = np.concatenate((in_distr[bins_limits],
 24                                           [in_distr[args[-1]]]))
 25         else:
 26             odd_bin = in_distr[args[bin_num * bin_size:]]
 27             bins_limits = np.arange(bin_num + 1) * bin_size
 28             bins_limits = args[bins_limits]
 29             bins_limits = in_distr[bins_limits]
 30             bins_limits = np.concatenate((bins_limits, [in_distr[args[-1]]]))
 31 
 32         return (hist, odd_bin, bins_limits)

Answer 1:

使用示例情况(2分,6个总数据点仓):

from scipy import stats
bin_edges = stats.mstats.mquantiles(data, [0, 2./6, 4./6, 1])
>> array([1. , 1.24666667, 2.05333333, 2.12])


Answer 2:

我还想提的存在pandas.qcut ,这不相等填充分级以非常有效的方式。 在你的情况下,它会工作像

data = np.array([1., 1.2, 1.3, 2.0, 2.1, 2.12])
# parameter q specifies the number of bins
qc = pd.qcut(data, q=3, precision=1)

# bin definition
bins  = qc.categories
print(bins)
>> Index(['[1, 1.3]', '(1.3, 2.03]', '(2.03, 2.1]'], dtype='object')

# bin corresponding to each point in data
codes = qc.codes
print(codes)
>> array([0, 0, 1, 1, 2, 2], dtype=int8)


Answer 3:

更新偏斜分布:

我碰到同样的问题@astabada,想要创建的每个包含样本的相等数目的二进制位。 当应用提出的解决方案@ aganders3,我发现,它并没有为偏态分布的工作特别好。 在倾斜的数据的情况下(例如一些与一大堆零), stats.mstats.mquantiles对于位数的预定数量将不能保证在每个仓样品的数目相等。 你会得到这个样子斌边缘:

[0. 0. 4. 9.]

在这种情况下,第一格是空的。

为了对付偏斜的情况下,我创建调用一个函数stats.mstats.mquantiles然后动态地修改窗口的数量,如果样本不一定的公差(在示例中代码的最小样本量的30%)内相等。 如果样本不仓之间相等,代码1降低等距分位数的数目,并调用stats.mstats.mquantiles再次直到样本大小是相等的或仅一个二进制位的存在。

我硬编码的例子中的耐受性,但如果需要的话,这可能被修改为一个关键字参数。

我还优选赋予相等间隔分位数的数目作为参数传递给我的函数而不是给用户定义的位数到stats.mstats.mquantiles为了减少偶然误差(即类似[0., 0.25, 0.7, 1.] ) 。

下面的代码:

import numpy as np 
from scipy import stats

def equibins(dat, binnum, **kwargs):
    numin = binnum
    while numin>1.:
        qtls = np.linspace(0.,1.0,num=numin,endpoint=False)
        ebins =stats.mstats.mquantiles(dat,qtls,alphap=kwargs['alpha'],betap=kwargs['beta'])
        allhist, allbin   = np.histogram(dat, bins = ebins)
        if (np.unique(ebins).shape!=ebins.shape or tolerence(allhist,0.3)==False) and numin>2:
            numin= numin-1
            del qtls, ebins
        else:
            numin=0
    return ebins

def tolerence(narray, percent):
    if percent>1.0:
        per = percent/100.
    else:
        per = percent
    lev_tol  = per*narray.min()
    tolerate = np.all(narray[1:]-narray[0]<lev_tol)
    return tolerate


Answer 4:

只是对数据进行排序,并通过长度将它分为固定库! 很显然,你不能分成正是同样填充箱,若样本数量不通过窗口的数量整除。

import math
import numpy as np
data = np.array([2,3,5,6,8,5,5,6,3,2,3,7,8,9,8,6,6,8,9,9,0,7,5,3,3,4,5,6,7])
data_sorted = np.sort(data)
nbins = 3
step = math.ceil(len(data_sorted)//nbins+1)
binned_data = []
for i in range(0,len(data_sorted),step):
    binned_data.append(data_sorted[i:i+step])


文章来源: Python: how to make an histogram with equally *sized* bins