从给定的数组创建一个“包装”的ndarray

时间:2022-09-16 12:53:46

I'm trying to create a 2D array from an array by using a rolled given array as the rows of the 2D array of a specified row dimension. For example:

我正在尝试通过使用滚动的给定数组作为指定行维度的2D数组的行来从数组创建2D数组。例如:

r = np.array([1,2,3,4])

want a matrix of 3 rows (using r) as

想要一个3行矩阵(用r)作为

[[2,3,4,1],
 [1,2,3,4],
 [4,1,2,3]]

I think I have an idea by defining a function using numpy.roll and a for-loop but I'm trying to avoid that as my 2D array is going to be very large. I would like to have the ability to roll backwards if possible.

我想我有一个想法,通过使用numpy.roll和for循环定义一个函数,但我试图避免这个,因为我的2D数组将会非常大。如果可能的话,我希望能够向后滚动。

Is there a way using numpy functions that can do this instead? Any suggestions on this are appreciated.

有没有办法使用numpy函数来代替?对此有任何建议表示赞赏。

3 个解决方案

#1


If using scipy is an option, you can use scipy.linalg.circulant. You will still have to tweak the argument to circulant to get exactly what you want, since circulant simply makes the given one-dimensional argument the first column of a square circulant matrix.

如果使用scipy是一个选项,您可以使用scipy.linalg.circulant。你仍然需要调整循环的参数以获得你想要的东西,因为循环只是使给定的一维参数成为正方形循环矩阵的第一列。

For example:

In [25]: from scipy.linalg import circulant

In [26]: r = np.array([1,2,3,4])

Here's what circulant gives:

这是循环给出的:

In [27]: circulant(r)
Out[27]: 
array([[1, 4, 3, 2],
       [2, 1, 4, 3],
       [3, 2, 1, 4],
       [4, 3, 2, 1]])

With some help from np.roll(), you can get your desired array:

在np.roll()的帮助下,您可以获得所需的数组:

In [28]: circulant(np.roll(r, -1)).T[:-1]
Out[28]: 
array([[2, 3, 4, 1],
       [1, 2, 3, 4],
       [4, 1, 2, 3]])

Or:

In [29]: circulant(np.roll(r[::-1], -1))[1:]
Out[29]: 
array([[2, 3, 4, 1],
       [1, 2, 3, 4],
       [4, 1, 2, 3]])

#2


This is a solution to the problem. It uses numpy's vstack to combine the rows into an array. It is maybe not the most efficient one though (I don't know the efficiency of res = np.vstack((res, r)) )

这是问题的解决方案。它使用numpy的vstack将行组合成一个数组。虽然它可能不是最有效的(我不知道res = np.vstack((res,r))的效率)

import numpy as np

def main():
    r = np.array([1,2,3,4])
    x = [i for i in range(1, len(r))] + [0]           # Forwards
    # x = [len(r)-1] + [i for i in range(len(r)-1)]     # Backwards
    r = r[x]
    res = r
    for c in range(2):
        r = r[x]
        res = np.vstack((res, r))
    print res
    return 0

if __name__ == '__main__':
    main()

It produces:

[[2 3 4 1]     'Forwards'
 [3 4 1 2]
 [4 1 2 3]]

[[4 1 2 3]     'Backwards'
 [3 4 1 2]
 [2 3 4 1]]

To change the order, it's only necessary to change the x = line.

要更改顺序,只需要更改x =行。

#3


Here's a simple solution using list indexing.

这是使用列表索引的简单解决方案。

r = [1, 2, 3, 4] # note: a list, so we can easily concatenate
result = np.array([r[i:] + r[:i] for i in range(1, len(r))])

array([[2, 3, 4, 1],
       [3, 4, 1, 2],
       [4, 1, 2, 3]])

This is pretty flexible because the indexing is still meaningful for negative values of i. So you just have to mess around with range to get the desired start and stop rows, and direction.

这非常灵活,因为索引对于i的负值仍然有意义。所以你只需要乱用范围来获得所需的开始和停止行和方向。

In particular, to get the exact result you wanted:

特别是,要获得您想要的确切结果:

np.array([r[i:] + r[:i] for i in range(1, -len(r) + 2, -1)])

array([[2, 3, 4, 1],
       [1, 2, 3, 4],
       [4, 1, 2, 3]])

#1


If using scipy is an option, you can use scipy.linalg.circulant. You will still have to tweak the argument to circulant to get exactly what you want, since circulant simply makes the given one-dimensional argument the first column of a square circulant matrix.

如果使用scipy是一个选项,您可以使用scipy.linalg.circulant。你仍然需要调整循环的参数以获得你想要的东西,因为循环只是使给定的一维参数成为正方形循环矩阵的第一列。

For example:

In [25]: from scipy.linalg import circulant

In [26]: r = np.array([1,2,3,4])

Here's what circulant gives:

这是循环给出的:

In [27]: circulant(r)
Out[27]: 
array([[1, 4, 3, 2],
       [2, 1, 4, 3],
       [3, 2, 1, 4],
       [4, 3, 2, 1]])

With some help from np.roll(), you can get your desired array:

在np.roll()的帮助下,您可以获得所需的数组:

In [28]: circulant(np.roll(r, -1)).T[:-1]
Out[28]: 
array([[2, 3, 4, 1],
       [1, 2, 3, 4],
       [4, 1, 2, 3]])

Or:

In [29]: circulant(np.roll(r[::-1], -1))[1:]
Out[29]: 
array([[2, 3, 4, 1],
       [1, 2, 3, 4],
       [4, 1, 2, 3]])

#2


This is a solution to the problem. It uses numpy's vstack to combine the rows into an array. It is maybe not the most efficient one though (I don't know the efficiency of res = np.vstack((res, r)) )

这是问题的解决方案。它使用numpy的vstack将行组合成一个数组。虽然它可能不是最有效的(我不知道res = np.vstack((res,r))的效率)

import numpy as np

def main():
    r = np.array([1,2,3,4])
    x = [i for i in range(1, len(r))] + [0]           # Forwards
    # x = [len(r)-1] + [i for i in range(len(r)-1)]     # Backwards
    r = r[x]
    res = r
    for c in range(2):
        r = r[x]
        res = np.vstack((res, r))
    print res
    return 0

if __name__ == '__main__':
    main()

It produces:

[[2 3 4 1]     'Forwards'
 [3 4 1 2]
 [4 1 2 3]]

[[4 1 2 3]     'Backwards'
 [3 4 1 2]
 [2 3 4 1]]

To change the order, it's only necessary to change the x = line.

要更改顺序,只需要更改x =行。

#3


Here's a simple solution using list indexing.

这是使用列表索引的简单解决方案。

r = [1, 2, 3, 4] # note: a list, so we can easily concatenate
result = np.array([r[i:] + r[:i] for i in range(1, len(r))])

array([[2, 3, 4, 1],
       [3, 4, 1, 2],
       [4, 1, 2, 3]])

This is pretty flexible because the indexing is still meaningful for negative values of i. So you just have to mess around with range to get the desired start and stop rows, and direction.

这非常灵活,因为索引对于i的负值仍然有意义。所以你只需要乱用范围来获得所需的开始和停止行和方向。

In particular, to get the exact result you wanted:

特别是,要获得您想要的确切结果:

np.array([r[i:] + r[:i] for i in range(1, -len(r) + 2, -1)])

array([[2, 3, 4, 1],
       [1, 2, 3, 4],
       [4, 1, 2, 3]])