没有中间体的Numpy索引

时间:2017-08-03 16:06:44

标签: python numpy indexing

以下代码是否首先创建一个中间件(用于保存rep[data]),然后将中间件复制到现有的out数组?

如果是这种情况,如何在不创建中间体的情况下执行此操作?

程序:

import numpy as np

data = np.array([0, 1, 0, 1, 1, 2, 1, 3])    
out = np.empty(data.shape)  # existing array
rep = np.array([1,3,5,7])
out[:] = rep[data]  # intermediate?

print(out)

结果:

[ 1.  3.  1.  3.  3.  5.  3.  7.]

感谢。

3 个答案:

答案 0 :(得分:3)

  

以下代码是否首先创建一个中间件(用于保存rep [data]),然后将中间件复制到现有的out数组中?

是。习惯于刮擦阵列; NumPy制作了很多,并且它们都不可避免。

  

如果是这种情况,如何在不创建中间体的情况下执行此操作?

简单的方法是

data = np.array([0, 1, 0, 1, 1, 2, 1, 3])    
rep = np.array([1,3,5,7])
out = rep[data]

但是如果你有一个现有的数组并且你真的需要用结果填充那个数组,你可以使用numpy.take

data = np.array([0, 1, 0, 1, 1, 2, 1, 3])    
out = np.empty(data.shape, dtype=int)
rep = np.array([1,3,5,7])
np.take(rep, data, out=out)

请注意,numpy.take 不像那样强大,因为它与一般的高级索引一样强大。

答案 1 :(得分:1)

一些探索性时间:

简单的索引返回:

In [286]: timeit out = rep[data]
357 ns ± 9.39 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

填写现有数组 - 更慢

In [287]: %%timeit out=np.empty(data.shape,data.dtype)
     ...: out[:] = rep[data]

1.15 µs ± 4.86 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

使用take填充数组,甚至更慢:

In [288]: %%timeit out=np.empty(data.shape,data.dtype)
     ...: np.take(rep, data, out=out)
5.94 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

我认为解释器将out[:] = rep[data]转换为:

out.__setitem__(slice(None), rep.__getitem__(data))

我们只有在编译版本为:

时才会避免缓冲
for i in range(...):
    out[i] = rep[data[i]]

我认为可以用nditer编写,但这只是编写Cython版本的一步。

In [324]: out=np.zeros(data.shape, data.dtype)
In [325]: it = np.nditer([data, out], op_flags=[['readonly'],['readwrite']])
In [326]: for x,y in it:
     ...:     y[...]=rep[x]
     ...:     
In [327]: out
Out[327]: array([1, 3, 1, 3, 3, 5, 3, 7])

答案 2 :(得分:0)

您可以简单地索引原始数组:

>>> rep[data]
array([1, 3, 1, 3, 3, 5, 3, 7])