11

データセットがあり、そのヒストグラムを作成したいと思います。ビンは同じサイズである必要があります。つまり、等間隔のビンを持つというより一般的な(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)は異なります。

2つの制限があります。-データのグループが同一である場合、それらを含むビンは大きくなる可能性があります。-N個のデータがあり、M個のビンが要求された場合、N / M個のビンに加えてN%Mが0でない場合は1個のビンがあります。

このコードは、私が書いたいくつかのくだらないものであり、小さなデータセットでうまく機能しました。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)
4

4 に答える 4

16

例のケースを使用すると(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])
于 2012-10-12T16:21:24.293 に答える
10

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)
于 2018-01-29T11:53:18.180 に答える
2

偏った分布の更新:

@astabadaと同じ問題に遭遇し、それぞれが同じ数のサンプルを含むビンを作成したいと考えました。@ aganders3で提案されたソリューションを適用すると、偏った分布では特にうまく機能しないことがわかりました。偏ったデータ(たとえば、ゼロがたくさんあるもの)の場合stats.mstats.mquantiles、事前定義された数の分位数に対して、各ビンに同じ数のサンプルが保証されるわけではありません。次のようなビンエッジが表示されます。

[0. 0. 4. 9.]

この場合、最初のビンは空になります。

偏ったケースに対処するために、stats.mstats.mquantilesサンプルが特定の許容範囲(サンプルコードの最小サンプルサイズの30%)内で等しくない場合に、ビンの数を呼び出して動的に変更する関数を作成しました。サンプルがビン間で等しくない場合、コードは等間隔の分位数の数を1減らし、stats.mstats.mquantilesサンプルサイズが等しくなるか、ビンが1つだけ存在するまで再度呼び出します。

この例では許容値をハードコーディングしましたが、必要に応じてこれをキーワード引数に変更できます。

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
于 2016-05-10T13:25:02.187 に答える
1

データを並べ替えて、長さで固定ビンに分割するだけです。明らかに、サンプルの数がビンの数で正確に除算されない場合、正確に均等に配置されたビンに分割することはできません。

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])
于 2017-08-31T17:05:17.077 に答える