将浮点值四舍五入到间隔限制/网格

时间:2018-07-24 15:15:32

标签: python arrays numpy

我有一个(随机)浮点数数组。我想将每个值四舍五入到任意网格的限制。请参见以下示例:

import numpy as np
np.random.seed(1)

# Setup
sample = np.random.normal(loc=20, scale=6, size=10)
intervals = [-np.inf, 10, 12, 15, 18, 21, 25, 30, np.inf]

# Round each interval up
for i in range(len(intervals) - 1):
    sample[np.logical_and(sample > intervals[i], sample <= intervals[i+1])] = intervals[i+1]

结果是:

[ 30.  18.  18.  15.  30.  10.  inf  18.  25.  21.]

如何避免for循环?我确定有某种方式可以使用NumPy的数组魔术,但现在还看不到。

5 个答案:

答案 0 :(得分:9)

如果intervals已排序,则可以使用np.searchsorted

np.array(intervals)[np.searchsorted(intervals, sample)]
# array([ 30.,  18.,  18.,  15.,  30.,  10.,  inf,  18.,  25.,  21.])

searchsorted返回元素所属间隔的索引:

np.searchsorted(intervals, sample)
# array([7, 4, 4, 3, 7, 1, 8, 4, 6, 5])

默认的side='left'返回该间隔的最小索引,结果属于左打开,右关闭的情况。

答案 1 :(得分:4)

您可以使用熊猫cut()

import pandas as pd

pd.cut(sample, intervals, labels=intervals[1:]).tolist()

答案 2 :(得分:1)

另一个选择是:

np.array(intervals)[(sample[:,None] > intervals).sum(axis=1)]
#array([30., 18., 18., 15., 30., 10., inf, 18., 25., 21.])

本质上,我们构建了一个遮罩,以检查样本是否大于间隔(假设它已按照示例中的顺序进行了排序)。然后,我们沿第一个轴求和,对于每个大于该值的间隔,该轴将合计1。

结果总和是intervals数组中的索引。

使用列表理解的非NumPy解决方案(显然包括for循环,但对于生成器而言应该相对有效):

new_sample = [next(i for i in intervals if i>s) for s in sample]
#[30, 18, 18, 15, 30, 10, inf, 18, 25, 21]

答案 3 :(得分:0)

没有运行检查,但是:

 from bisect import bisect

 for index, value in enumerate(sample):
     sample[index] = intervals[ bisect( intervals, value)]

答案 4 :(得分:0)

如果values是具有您的值的一维数组,则可以执行类似的操作

diff = values < intervals[:, None]
t = np.argmax(diff, axis=0)
new_values = intervals[t]