我想创建一个函数,将一个范围[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))
任何建议/指示赞赏!
答案 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有多好。当然不会很快。