Python Bins / Numpy Digitize - 从中​​点

时间:2017-02-05 22:19:04

标签: python numpy

我想创建一个函数,将一个范围[0,1]内的数字放入一个bin中,其中n是bin的数量,边界是相对于中点定义的。

0.0 >= Bin 1 <= 0.2 <- outer left bin
0.2 > Bin 2 <= 0.4
0.4 > Bin 3 < 0.6  <- middle bin    
0.6 >= Bin 4 < 0.8
0.8 >= Bin 5 <= 1 <- outer right bin

我以为我能够做到以下几点:

def fractile(x, n):
    bins = np.linspace(0.0, 1.0, n+1)
    return np.where(x > 0.5,
                    np.digitize(x, bins, right=False),
                    np.digitize(x, bins, right=True))

x = pd.DataFrame(np.linspace(0.05, 0.95, 19))
f = fractile(x, 10)

n = 10的结果:

array([[ 1],
   [ 1],
   [ 2],
   [ 2],
   [ 3],
   [ 3],
   [ 4],
   [ 4],
   [ 5],
   [ 5],
   [ 6],
   [ 6],
   [ 7],
   [ 7],
   [ 8],
   [ 8],
   [ 9],
   [10],
   [10]], dtype=int64)

我希望中间是最小的垃圾箱,但会得到意想不到的结果......

参考下面的Pauls答案可以在评估之前修改函数以进行舍入,从而减轻浮点运算问题,但看起来很难看:

def fractile(x, n):
    x = np.round(x, 15)
    bins = np.round(np.linspace(0.0, 1.0, n+1), 15)
    return np.where(x > 0.5,
                    np.digitize(x, bins, right=False),
                    np.digitize(x, bins, right=True))

任何建议/指示赞赏!

1 个答案:

答案 0 :(得分:0)

您只是遇到浮点运算的不准确性。要查看它与您的特定功能无关,请尝试例如

>>> np.digitize(np.linspace(0.05,0.95,19), np.linspace(0,1,11))
array([ 1,  2,  2,  3,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,  9,
   10, 10])

或直接

>>> np.linspace(0.05,0.95,19) == np.linspace(0,1,21)[1:-1]
array([ True,  True, False,  True,  True, False, False, False, False,
   False, False, False,  True, False,  True, False, False,  True, False], dtype=bool)                                                             

如果您需要精确的边界,请尽可能使用整数。如果没有,则有分数模块。不过,不确定它与numpy有多好。当然不会很快。