python-3.x 向量到相邻向量的数组

hivapdat  于 2023-02-06  发布在  Python
关注(0)|答案(2)|浏览(124)

我想取一个向量,得到一个向量数组,其中每个向量的第i个元素,是原始向量的第i个元素的k个邻居,我也在寻找最快的方法。
我已经在MATLAB里做过了

a=zeros(k, length(v));   
I=cell(1,k);

a(1,:) = v;

for j=2:k
    a(k,:)=[a(k-1,2:end),a(k-1,1)];
end

aux1=[a(:,(end-r+1):end),a(:,1:(end-r))];

for j=1:k
    I{k}=aux1(k,:);
end

例如,v = [1,2,3,4,5]且k = 1;我想得到:
M = [[5, 1, 2, 3, 4], [1, 2, 3, 4, 5], [2, 3, 4, 5, 1]]
因此,对于每个向量的第一个元素,我得到[5;1; 2],它们是元素1及其相邻元素。
希望有道理。谢谢阅读:)

euoag5mw

euoag5mw1#

可以使用numpy roll函数:

import numpy as np

def get_neighbors(v, k):
    N = len(v)
    M = np.zeros((k*2+1, N), dtype=int)
    for i in range(-k, k+1):
        M[i+k, :] = np.roll(v, -i)
    return M

v = np.array([1, 2, 3, 4, 5])
k = 1
M = get_neighbors(v, k)
print(M)

输出:

[[5 1 2 3 4]
 [1 2 3 4 5]
 [2 3 4 5 1]]
xurqigkl

xurqigkl2#

对数组的重复使用sliding_window_view可以"矢量化"方式执行此操作

# Example array
a = np.arange(1,16)
k = 2 # Window of neighbors

# My solution
np.lib.stride_tricks.sliding_window_view(np.hstack([a,a,a]), (len(a),))[len(a)-k:len(a)+k+1]

返回

array([[14, 15,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13],
       [15,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14],
       [ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  1],
       [ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  1,  2]])

注意sliding_window_view只创建了一个视图,并没有创建新的数据,因此我毫不犹豫地创建了(在这个例子中)31行(3 * 15 - 15 + 1),然后只对其中的5行进行子集化:我并没有真正创建它们,所以这个解决方案的真正成本是hstack,包括cpu和内存。
顺便说一句,这个子集是为了严格遵守你的要求而做的。但是,根据你的意图,你可能会放弃这个子集。

T=np.lib.stride_tricks.sliding_window_view(np.hstack([a,a,a]), (len(a),))

那么T[len(a)+k]是由第k个邻居组成的行,无论k是正、负还是0(原始行)
查看时间,因为它对您很重要
| 大小|这种方法|滚动法|
| - ------|- ------|- ------|
| 透镜= 15/k = 2|51微秒|132微秒|
| 透镜= 15/k = 7|51微秒|383微秒|
| 透镜= 1000/k = 7|52微秒|422微秒|
| 透镜= 1M/k = 7|6毫秒|160毫秒|
| 透镜= 1M/k = 100|6毫秒|2.2秒|
Roll方法显然与窗口大小成正比(O(k)--每行输出执行一次Roll),当sliding_window_view只是一个视图,并不真正创建行时,O(1)也是如此。两种方法受数据len的影响是相同的(O(n),但它只显示n足够大)。
总的来说,这个方法是O(n),而滚动方法是O(kn)

相关问题