首页 > 解决方案 > 填充 scipy.sparse.dok_matrix 的最快方法

问题描述

根据输入列表填充 scipy.sparse.dok_matrix 的最有效方法是什么?

事先不知道 dok_matrix 中的列数或行数。

行数是输入列表的长度,列数取决于输入列表中的值。

显而易见的:

def get_dok_matrix(values: List[Any]) -> scipy.sparse.dok_matrix:
    max_cols = 0
    datas = []
    for value in values:
        data = get_data(values)
        datas.append(data)
        if len(data) > max_cols:
            max_cols = len(data)
    dok_matrix = scipy.sparse.dok_matrix((len(values), max_cols))
    for i, data in enumerate(datas):
        for j, datum in enumerate(data):
            dok_matrix[i, j] = datum
    return dok_matrix

有两个 for 循环,一个嵌套 for 循环,还有许多len()检查。我无法想象这是非常有效的。

我也考虑过:

def get_dok_matrix(values: List[Any]) -> scipy.sparse.dok_matrix:
    cols = 0
    dok_matrix = scipy.sparse.dok_matrix((0, 0))
    for row, value in enumerate(values):
        dok_matrix.resize(row + 1, cols)
        data = get_data(values)
        for col, datum in enumerate(data):
            if col + 1 > cols:
                cols = col + 1
                dok_matrix.resize(row + 1, cols)
            dok_matrix[row, col] = datum
    return dok_matrix

这在很大程度上取决于效率如何scipy.sparse.dok_matrix.resize,我在文档中找不到。

其中哪个最有效?

有没有更好的方法让我错过(也许我可以 O(1) 一次设置一整行?)?

标签: pythonpython-3.xnumpyscipy

解决方案


和:

def get_dok_matrix(values):
    max_cols = 0
    datas = []
    for value in values:
        data = value         # changed
        datas.append(data)
        if len(data) > max_cols:
            max_cols = len(data)
    dok_matrix = sparse.dok_matrix((len(values), max_cols))
    for i, data in enumerate(datas):
        for j, datum in enumerate(data):
            dok_matrix[i, j] = datum
    return dok_matrix

In [13]: values = [[1],[1,2],[1,2,3],[4,5,6,7],[8,9,10,11,12]]
In [14]: dd = get_dok_matrix(values)
In [15]: dd
Out[15]: 
<5x5 sparse matrix of type '<class 'numpy.float64'>'
    with 15 stored elements in Dictionary Of Keys format>
In [16]: dd.A
Out[16]: 
array([[ 1.,  0.,  0.,  0.,  0.],
       [ 1.,  2.,  0.,  0.,  0.],
       [ 1.,  2.,  3.,  0.,  0.],
       [ 4.,  5.,  6.,  7.,  0.],
       [ 8.,  9., 10., 11., 12.]])

我希望您提供了一个values示例,这样我就不必研究您的代码并创建一个可以使用它的代码。

制作coo格式:

def get_coo_matrix(values):
    data, row, col = [],[],[]
    for i,value in enumerate(values):
        n = len(value)
        data.extend(value)
        row.extend([i]*n)
        col.extend(list(range(n)))
    return sparse.coo_matrix((data,(row,col)))

In [18]: M = get_coo_matrix(values)
In [19]: M
Out[19]: 
<5x5 sparse matrix of type '<class 'numpy.int64'>'
    with 15 stored elements in COOrdinate format>
In [20]: M.A
Out[20]: 
array([[ 1,  0,  0,  0,  0],
       [ 1,  2,  0,  0,  0],
       [ 1,  2,  3,  0,  0],
       [ 4,  5,  6,  7,  0],
       [ 8,  9, 10, 11, 12]])

次:

In [22]: timeit dd = get_dok_matrix(values)
431 µs ± 10.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [23]: timeit M = get_coo_matrix(values)
152 µs ± 524 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

推荐阅读