我想创建一个函数,将[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))
任何建议/建议,不胜感激!
您正经历浮点运算的不准确。要查看它与您的特定功能无关,请尝试例如
>>> 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玩得有多好。当然不会很快。