我有以下双端队列对象:
test = deque([np.zeros((4,1,1))+0.5] * 25)
所以有25种形状的数组,我将附加对象,在另一端弹出旧的对象,等等。
在某些时候,我想在我的双端队列中选择一个元素子集:
>>> idx = np.round(np.linspace(0, 20, 4, dtype='int'))
>>> idx
array([ 0, 6, 13, 20])
所以我想要那些指示。我尝试过:
>>> test[idx]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: only integer scalar arrays can be converted to a scalar index
也许双端队列不支持这种类型的索引操作。如何从idx
轻松(高效)获得test
中的元素列表?
编辑-
有关我最初目标的更多信息。我有一个3D numpy数组的列表,即(N, H,W,3)
,实时地,我正在将一个新的3D数组移到N
的列表中,即,一个大小为(H,W,3)
的新数组被移位了(就像一个队列)进入N列表。
对所有内容都使用形状为(N, H,W,3)
的numpy数组会很好,但是我不知道如何获得有效的队列功能,所以我选择了deque
。
答案 0 :(得分:2)
要直接回答您的问题,请使用与列表-[test[i] for i in idx]
相同的可迭代索引对双端队列进行索引。但是双端队列随机查找是O(n)
(对于较大的双端队列可能更重要),如果您想对双端队列进行NumPy样式索引,则将无法执行。从问题描述中,这听起来也像您在寻找环形缓冲区。
因此,根本不使用双端队列,坚持NumPy可能是一个更好的主意(对于较大的双端队列大小,效率更高)。
现在,您可以在管理缓冲区大小,左/右索引等的ndarray周围滚动自己的类似双端队列的环形缓冲区接口类。或者Eric Weiser已经发布了numpy_ringbuffer
,看上去很不错-适合您的问题。
演示
In [83]: from numpy_ringbuffer import RingBuffer
In [84]: # RingBuffer w/ capacity 3, extra dimensions (2, 2)
...: r = RingBuffer(capacity=3, dtype=(float, (2, 2)))
In [85]: # fill our buffer up
...: r.extendleft(np.arange(12, dtype=float).reshape(3, 2, 2))
In [86]: r.is_full
Out[86]: True
In [87]: r
Out[87]:
<RingBuffer of array([[[ 0., 1.],
[ 2., 3.]],
[[ 4., 5.],
[ 6., 7.]],
[[ 8., 9.],
[10., 11.]]])>
In [88]: r.appendleft(np.arange(12, 16).reshape(2, 2))
In [89]: r
Out[89]:
<RingBuffer of array([[[12., 13.],
[14., 15.]],
[[ 0., 1.],
[ 2., 3.]],
[[ 4., 5.],
[ 6., 7.]]])>
您将获得带有append
,extend
,pop
和左版本的最小双端队列接口。您还可以在基础数组上使用NumPy索引。
In [90]: r[[0, 2]]
Out[90]:
array([[[12., 13.],
[14., 15.]],
[[ 4., 5.],
[ 6., 7.]]])
与NumPy中类似双端队列操作的天真的方法相比,它将更快,因为它仅在可能的情况下操纵左/右索引。
In [91]: arr = np.random.randn(10**7).reshape(10**5, 10, 10)
In [92]: r = RingBuffer(capacity=arr.shape[0],
...: dtype=(float, arr.shape[1:]))
...:
In [93]: %%timeit r.extendleft(arr); s = np.random.randn(10, 10)
...: r.appendleft(s)
...: r.append(s)
...:
4.08 µs ± 66.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [94]: %%timeit A=arr.copy(); s = np.random.randn(10, 10)
...: A[1:] = A[:-1]
...: A[0] = s
...: A[:-1] = A[1:]
...: A[-1] = s
...:
91.5 ms ± 231 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)