从主数据阵列生成二维稀疏数组的快速方法

时间:2016-10-11 07:56:37

标签: python numpy indexing sparse-matrix

我将通过一个我想做的例子来简化我的问题(我正在使用的实际数据非常庞大)。

如果有一个3维稀疏数组对象可以输入x,y,z坐标以及要存储的数据,那么我的问题的解决方案将很简单。请注意,如果我不使用稀疏数组,我将遇到内存问题。让我们说我有一个阵列:

    import numpy as np
    from scipy.sparse import coo_matrix
    arr=np.array([1,3,4,5],[0,6,7,8],[1,7,8,7]])

前3个条目是x,y,z。理想情况下,我想要一个稀疏矩阵 这会产生B [1,3,4] = 5和B [0,6,7] = 8等。现在我正在使用一个字典,其中x坐标是关键。 y和z将是稀疏数组坐标。所以它是这样的:

    row=arr[:,1]
    col=arr[:,2]
    data=arr[:,3]
    dic={}
    ### x here goes from only 0 to 1 in this simple example
    for x in range(2):
        bool=arr[:,0][arr[:,0]==x] ####### this step takes too long
        ###### now create sparse matrix for all data with 
        ###### x value equal to the iterator
        dic[x]=coo_matrix((data[bool], (row[bool],     
        col[bool])), shape=(1536, 32768)) ### this part ok

所以我记下的bool测试是占据90%的时间的步骤。这是因为我的阵列非常庞大。 理想情况下,我想直接将所有内容编入索引。

解决方案?

谢谢!

谢谢!

1 个答案:

答案 0 :(得分:0)

这是另一种方法 -

out_shp = (10,10)  # (1536, 32768) for your actual case
out_dic = {}
for i in np.unique(arr[:,0]):
    RCD = arr[arr[:,0] == i,1:]
    out_dic[i] = coo_matrix((RCD[:,2],(RCD[:,0],RCD[:,1])), shape=out_shp)

示例输入,输出 -

In [87]: arr
Out[87]: 
array([[1, 3, 4, 5],
       [0, 6, 7, 8],
       [1, 7, 8, 7]])

In [88]: out_dic[0].toarray()
Out[88]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 8, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

In [89]: out_dic[1].toarray()
Out[89]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 5, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 7, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

这是另一种方法,它在进入循环之前根据第一列对数组进行排序,并简单地在循环内切片。这是一种专注于性能的方法,因为我们将在循环内进行较少的计算,因为这似乎是瓶颈。所以,我们会有另外一个实现 -

s_arr = arr[arr[:,0].argsort()] # Sorted array
unq,start_idx = np.unique(s_arr[:,0],return_index=1)
stop_idx = np.append(start_idx[1:],arr.shape[0])
out_shp = (10,10)  # (1536, 32768) for your actual case
out_dic = {}
for i,u in enumerate(unq):
    RCD = s_arr[start_idx[i]:stop_idx[i],1:] # Row-col-data
    out_dic[u] = coo_matrix((RCD[:,2],(RCD[:,0],RCD[:,1])), shape=out_shp)
相关问题