在2D数组上放置列表元素的快速方法

时间:2018-06-22 08:27:16

标签: python arrays list

我有两个列表,两个列表都称为位置和值。位置和值的每个子列表都包含2D数组中在时间k = 1,..,n处的峰的位置和值。例如

values    = [[5,1,1,8,10],[3,1,7,9,4]]
positions = [[(0,0),(1,2),(1,4),(3,3),(4,4)],[(0,1),(1,3),(2,4),(3,4),(4,0)]]

在此,列表[5,1,1,8,10]是2D数组上的值,[[0,0),(1,2 ,,(1,4),(3,3) ,,(4,4)]是这些值在时间0处的对应位置。同样,[3,1,7,9,4]是2D数组上的值,[[0,1),(1,3),(2,4),(3,4),(4,0 )]是这些值在时间1的对应位置。我想将这些值放在二维零数组上的相应位置。所以我做了以下功能

import itertools

def list_to_array(n_1, n_2, positions, values):

    new_array_list = []

    for k in range(len(positions)):

        A = np.zeros((n_1,n_2))

        for i, j in itertools.product(range(n_1), range(n_2)):

            if (i,j) in positions[k]:

                X = positions[k].index((i,j))
                A[i,j] = values[k][X]

        new_array_list += [A]

    return new_array_list

这应该返回两个数组

A[0] = [[  5.   0.   0.   0.   0.]
 [  0.   0.   1.   0.   1.]
 [  0.   0.   0.   0.   0.]
 [  0.   0.   0.   8.   0.]
 [  0.   0.   0.   0.  10.]]

A[1] = [[ 0.  3.  0.  0.  0.]
 [ 0.  0.  0.  1.  0.]
 [ 0.  0.  0.  0.  7.]
 [ 0.  0.  0.  0.  9.]
 [ 4.  0.  0.  0.  0.]]

对于256x256数组,单个迭代大约需要一秒钟,我需要对1600个列表执行迭代,这虽然很长,但仍然很合理。但是,我也希望对更大的数组(每个方向的长度最多8倍)执行此操作,因此很明显,上面的代码将花费太长时间。我想知道是否有人知道更快的方法?

2 个答案:

答案 0 :(得分:3)

您可以使用专家库。在这种情况下,NumPy提供了矢量化解决方案。

对于较大的数字数据结构,列表列表方法效率低下,因为它将使用指针集合。相反,NumPy利用连续的内存块来实现有效的数值转换。

import numpy as np

values    = [[5,1,1,8,10],[3,1,7,9,4]]
positions = [[(0,0),(1,2),(1,4),(3,3),(4,4)],[(0,1),(1,3),(2,4),(3,4),(4,0)]]

# convert to NumPy arrays of shapes (10,) and (10, 2)      
val = np.array(values).flatten()
pos = np.array(positions).reshape(-1, 2)

# initialize array of zeros
arr = np.zeros(pos.max(0)+1)

# assign values to positions
arr[[*pos.T]] = val

print(arr)

array([[  5.,   3.,   0.,   0.,   0.],
       [  0.,   0.,   1.,   1.,   1.],
       [  0.,   0.,   0.,   0.,   7.],
       [  0.,   0.,   0.,   8.,   9.],
       [  4.,   0.,   0.,   0.,  10.]])

如果根据您的更新,您需要2个单独的阵列,则可以重复此过程:

# convert to NumPy arrays of shapes (10,) and (10, 2)      
val1, val2 = (np.array(v).flatten() for v in values)
pos1, pos2 = (np.array(p).reshape(-1, 2) for p in positions)

# initialize array of zeros
arr1 = np.zeros(pos1.max(0)+1)
arr2 = np.zeros(pos2.max(0)+1)

# assign values to positions
arr1[[*pos1.T]] = val1
arr2[[*pos2.T]] = val2

答案 1 :(得分:1)

您可以这样做:

import itertools
import numpy as np
def list_to_array(n_1, n_2, positions, values):

    new_array_list = []

    for k in range(len(positions)):

        A = np.zeros((n_1,n_2))

        for i in range(len(positions[k])):
            A[positions[k][i]] = values[k][i]
        new_array_list += [A]

    return new_array_list

values    = [[5,1,1,8,10],[3,1,7,9,4]]
positions = [[(0,0),(1,2),(1,4),(3,3),(4,4)],[(0,1),(1,3),(2,4),(3,4),(4,0)]]

print list_to_array(5,5,positions,values)