以下代码是否首先创建一个中间件(用于保存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.]
感谢。
答案 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])