从浮点索引到数组的快速查找

时间:2016-09-27 10:11:29

标签: python numpy optimization floating-point indices

假设我在轴上有nlen个区间长度ndarray。它们中的每一个都被赋予query_pos中的值。现在我想查找以浮点数给出的位置n = 100 len = 0.39483 data = ... # creates ndarray with data of length n = 100 query_pos = ... # creates an ndarray with positions to query values_at_query_pos = data[(query_pos / len).astype(int)] # questionable line 处的一些值。目前,我计划采用以下方式:

astype(int)

这是一个很好的方法吗?还是有更有效的方法将浮点查询位置转换为整数索引然后从数组中读取?我特别想知道,还是{{1例如,与分区或内存读取相比,这是一种廉价或昂贵的操作。

更多评论:

  • 最后,它将用于2维和3维。目前,我打算 在之前找到会导致非法指数的位置 进入查询阶段。

  • data阵列具有足够高的分辨率,因此我不会这样做 需要任何过滤或插值。这将在以前完成 阶段。

2 个答案:

答案 0 :(得分:4)

不是将query_pos的每个元素除以该标量,我们可以预先计算标量的倒数,并使用乘法代替那里的某些加速。直觉是分裂比乘法更昂贵。

这是一个快速的运行时测试 -

In [177]: # Setup inputs
     ...: n = 100
     ...: len1 = 0.39483
     ...: data = np.random.rand(100)
     ...: query_pos = np.random.randint(0,25,(100000))
     ...: 

In [178]: %timeit query_pos / len1
1000 loops, best of 3: 612 µs per loop

In [179]: %timeit query_pos * (1/len1)
10000 loops, best of 3: 173 µs per loop

其次,如果有许多重复索引,就像前面显示的运行时测试所使用的设置一样,我们可以使用np.take进行进一步的边际改进,如下所示 -

In [196]: %timeit data[(query_pos *(1/len1)).astype(int)]
1000 loops, best of 3: 538 µs per loop

In [197]: %timeit np.take(data,(query_pos * (1/len1)).astype(int))
1000 loops, best of 3: 526 µs per loop

如果您打算在通用ndarrays上使用它,我们需要将axis param与np.take一起使用。

将其与原始方法进行比较 -

In [202]: %timeit data[(query_pos / len1).astype(int)]
1000 loops, best of 3: 967 µs per loop

最后,关于除法运算如何与转换为int叠加的问题,它们在大数据集上似乎具有可比性。但是,似乎你无法避免索引所需的转换。这是一个时间测试 -

In [210]: idx = query_pos * (1/len1)

In [211]: %timeit query_pos * (1/len1)
10000 loops, best of 3: 165 µs per loop

In [212]: %timeit idx.astype(int)
10000 loops, best of 3: 110 µs per loop

答案 1 :(得分:1)

您可以将分部的结果直接输出到int数组:

idx = np.empty_like(query_pos, int)
np.divide(query_pos, len, out=idx, casting='unsafe')

这对于大型阵列来说明显更快。但是这段代码难以阅读,所以只有在它成为瓶颈的情况下才能优化!