如何在 for 循环中获取 lil_matrix 元素的索引?
How to get indices of lil_matrix elements in a for loop?
我使用 scipy.sparse.lil_matrix
创建了一个稀疏矩阵:
import scipy.sparse as sp
test = sp.lil_matrix((3,3))
test[0,0]=1
我可以循环并打印非零元素:
for el in test:
print(el)
打印出 (0, 0) 1.0
。如何在不打印的情况下访问这两条信息?换句话说,lil_matrix
的元素和 return 索引和值的适当方法是什么?做 el.data
returns array([list([])], dtype=object)
.
请注意,我使用的是 lil_matrix
,因为我需要在一个非常大的双 for 循环中为其分配非零值。
都在.data
和.rows
from scipy import sparse
arr = sparse.random(10,5,format='lil', density=0.5)
对于这个包含 25 个元素的 10x5 数组:
>>> arr
<10x5 sparse matrix of type '<class 'numpy.float64'>'
with 25 stored elements in List of Lists format>
>>> arr.data.shape
(10,)
>>> arr.data
array([list([0.7656088763162588, 0.7262695483137545]),
list([0.5229054168281109, 0.6329489698531673, 0.9090750679268123]),
list([0.3285250285217297, 0.12678874412598085, 0.49074613569184733]),
list([0.9376762935882884]), list([0.7783159122917774]),
list([0.8750078624527947, 0.017065437987856757, 0.7161352157970525]),
list([0.6849637433019786, 0.05732598765212671, 0.09948536587262824]),
list([0.5683250727980487, 0.960851197599538, 0.7540173942047833]),
list([0.5891879469424754, 0.7901005027272154, 0.5829700379167293]),
list([0.6266097436787399, 0.8843420498719459, 0.9040791506861361])],
dtype=object)
.data
数组的每个元素都是一个列表,其中包含该行的值。
>>> arr.rows
array([list([0, 4]), list([0, 1, 4]), list([1, 3, 4]), list([1]),
list([3]), list([0, 1, 2]), list([0, 1, 4]), list([1, 2, 3]),
list([0, 2, 4]), list([0, 1, 3])], dtype=object)
.rows
数组的每个元素都是 .data
.
中每个 non-zero 值的列索引列表
Note that I'm using lil_matrix because I will need to assign nonzero values to it within a very large, double for loop.
这几乎肯定不是一个好主意。 lil_matrix
的开销意味着如果它的稀疏度不少于 5%,那么填充密集数组几乎肯定会更好。即使那样,它也很不确定。这是一种非常糟糕的数据存储格式。
编辑:
>>>> for r in arr:
>>>> print(r.data)
[list([0.7656088763162588, 0.7262695483137545])]
[list([0.5229054168281109, 0.6329489698531673, 0.9090750679268123])]
[list([0.3285250285217297, 0.12678874412598085, 0.49074613569184733])]
[list([0.9376762935882884])]
[list([0.7783159122917774])]
[list([0.8750078624527947, 0.017065437987856757, 0.7161352157970525])]
[list([0.6849637433019786, 0.05732598765212671, 0.09948536587262824])]
[list([0.5683250727980487, 0.960851197599538, 0.7540173942047833])]
[list([0.5891879469424754, 0.7901005027272154, 0.5829700379167293])]
[list([0.6266097436787399, 0.8843420498719459, 0.9040791506861361])]
编辑 2:
我不知道你的实际功能或目标是什么,但如果你知道你有多少 non-zero 项,你可以预先分配你需要的数组并跳过整个 lil 事情。
import numpy as np
N = 10000
data, rows, cols = np.zeros(N), np.zeros(N), np.zeros(N)
for i, r in enumerate(_):
for j, c in enumerate(_):
_idx = i * len(cols) + j
data[_idx] = some_data_function()
rows[_idx] = r
cols[_idx] = c
arr = sparse.csr_matrix((data, (rows, cols)))
您寻找的显示很像 coo
稀疏矩阵的 str
显示。
In [216]: M = (sparse.random(5,5,.2)*10).astype(int)
In [217]: M
Out[217]:
<5x5 sparse matrix of type '<class 'numpy.int64'>'
with 5 stored elements in COOrdinate format>
In [218]: print(M) # str(M)
(0, 0) 0
(0, 2) 8
(1, 3) 8
(1, 4) 8
(4, 4) 4
稀疏矩阵有一个 nonzero
方法来显示非零元素的坐标。
In [219]: M.nonzero()
Out[219]: (array([0, 1, 1, 4], dtype=int32), array([2, 3, 4, 4], dtype=int32))
对于 coo
,值存储为 3 个数组:
In [220]: M.data, M.row, M.col
Out[220]:
(array([0, 8, 8, 8, 4]),
array([0, 0, 1, 1, 4], dtype=int32),
array([0, 2, 3, 4, 4], dtype=int32))
coo
格式中这些元素的顺序没有限制。甚至可以有重复项,尽管在转换为显示或 csr
格式时会将它们相加。
当我们将其转换为 lil
格式时,数据现在存储在 2 个列表数组中,每行一个列表:
In [221]: Ml = M.tolil()
In [222]: Ml.data
Out[222]:
array([list([0, 8]), list([8, 8]), list([]), list([]), list([4])],
dtype=object)
In [223]: Ml.rows
Out[223]:
array([list([0, 2]), list([3, 4]), list([]), list([]), list([4])],
dtype=object)
它也有nonzero
,但看代码(它使用coo
格式):
In [224]: Ml.nonzero()
Out[224]: (array([0, 1, 1, 4], dtype=int32), array([2, 3, 4, 4], dtype=int32))
In [225]: Ml.nonzero??
Signature: Ml.nonzero()
Source:
def nonzero(self):
...
# convert to COOrdinate format
A = self.tocoo()
nz_mask = A.data != 0
return (A.row[nz_mask], A.col[nz_mask])
File: /usr/local/lib/python3.6/dist-packages/scipy/sparse/base.py
Type: method
实际上,这是所有稀疏格式的通用 nonzero
。 nz_mask
部分允许矩阵可能有 0 个未被清理的值。
虽然 lil
旨在轻松逐个元素更新,但我们通常建议尽可能从 coo
样式的输入数组创建矩阵。通常可以更有效地创建这些数组。甚至列表追加或扩展也可以更快。
更多地关注 Ml
矩阵的迭代 - 它为每一行创建一个 lil
:
In [230]: [x for x in Ml]
Out[230]:
[<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 2 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 2 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 0 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 0 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 1 stored elements in List of Lists format>]
我们可以显示每一行的数据:
In [231]: [((i,x.rows[0]),x.data[0]) for i,x in enumerate(Ml)]
Out[231]:
[((0, [0, 2]), [0, 8]),
((1, [3, 4]), [8, 8]),
((2, []), []),
((3, []), []),
((4, [4]), [4])]
或过滤掉空行:
In [232]: [((i,x.rows[0]),x.data[0]) for i,x in enumerate(Ml) if x.data[0]]
Out[232]: [((0, [0, 2]), [0, 8]), ((1, [3, 4]), [8, 8]), ((4, [4]), [4])]
我们需要另一次迭代来分离每行中的元素。
关于稀疏数组与密集数组的使用,一条经验法则是稀疏度(非零元素的百分比)应小于 10% 才值得使用稀疏格式。但这在很大程度上取决于您的使用和关注。
从简单的数据存储角度来看,请注意 coo
格式必须为每个非零项使用 3 个数字,而不是密集数组仅使用 1 个数字。稀疏矩阵乘法对于 csr
格式比较好。其他可以只关注 data
值(例如 sin
)的计算也相对有效。但是如果数学必须比较2个矩阵的稀疏性,比如加法和element-wise乘法,稀疏的情况更糟。
索引、切片和求和实际上可能使用矩阵乘法。 coo
格式没有实现这些。 lil
可以很好地完成一些面向行的操作。创建稀疏矩阵的基本操作需要时间。
我使用 scipy.sparse.lil_matrix
创建了一个稀疏矩阵:
import scipy.sparse as sp
test = sp.lil_matrix((3,3))
test[0,0]=1
我可以循环并打印非零元素:
for el in test:
print(el)
打印出 (0, 0) 1.0
。如何在不打印的情况下访问这两条信息?换句话说,lil_matrix
的元素和 return 索引和值的适当方法是什么?做 el.data
returns array([list([])], dtype=object)
.
请注意,我使用的是 lil_matrix
,因为我需要在一个非常大的双 for 循环中为其分配非零值。
都在.data
和.rows
from scipy import sparse
arr = sparse.random(10,5,format='lil', density=0.5)
对于这个包含 25 个元素的 10x5 数组:
>>> arr
<10x5 sparse matrix of type '<class 'numpy.float64'>'
with 25 stored elements in List of Lists format>
>>> arr.data.shape
(10,)
>>> arr.data
array([list([0.7656088763162588, 0.7262695483137545]),
list([0.5229054168281109, 0.6329489698531673, 0.9090750679268123]),
list([0.3285250285217297, 0.12678874412598085, 0.49074613569184733]),
list([0.9376762935882884]), list([0.7783159122917774]),
list([0.8750078624527947, 0.017065437987856757, 0.7161352157970525]),
list([0.6849637433019786, 0.05732598765212671, 0.09948536587262824]),
list([0.5683250727980487, 0.960851197599538, 0.7540173942047833]),
list([0.5891879469424754, 0.7901005027272154, 0.5829700379167293]),
list([0.6266097436787399, 0.8843420498719459, 0.9040791506861361])],
dtype=object)
.data
数组的每个元素都是一个列表,其中包含该行的值。
>>> arr.rows
array([list([0, 4]), list([0, 1, 4]), list([1, 3, 4]), list([1]),
list([3]), list([0, 1, 2]), list([0, 1, 4]), list([1, 2, 3]),
list([0, 2, 4]), list([0, 1, 3])], dtype=object)
.rows
数组的每个元素都是 .data
.
Note that I'm using lil_matrix because I will need to assign nonzero values to it within a very large, double for loop.
这几乎肯定不是一个好主意。 lil_matrix
的开销意味着如果它的稀疏度不少于 5%,那么填充密集数组几乎肯定会更好。即使那样,它也很不确定。这是一种非常糟糕的数据存储格式。
编辑:
>>>> for r in arr:
>>>> print(r.data)
[list([0.7656088763162588, 0.7262695483137545])]
[list([0.5229054168281109, 0.6329489698531673, 0.9090750679268123])]
[list([0.3285250285217297, 0.12678874412598085, 0.49074613569184733])]
[list([0.9376762935882884])]
[list([0.7783159122917774])]
[list([0.8750078624527947, 0.017065437987856757, 0.7161352157970525])]
[list([0.6849637433019786, 0.05732598765212671, 0.09948536587262824])]
[list([0.5683250727980487, 0.960851197599538, 0.7540173942047833])]
[list([0.5891879469424754, 0.7901005027272154, 0.5829700379167293])]
[list([0.6266097436787399, 0.8843420498719459, 0.9040791506861361])]
编辑 2:
我不知道你的实际功能或目标是什么,但如果你知道你有多少 non-zero 项,你可以预先分配你需要的数组并跳过整个 lil 事情。
import numpy as np
N = 10000
data, rows, cols = np.zeros(N), np.zeros(N), np.zeros(N)
for i, r in enumerate(_):
for j, c in enumerate(_):
_idx = i * len(cols) + j
data[_idx] = some_data_function()
rows[_idx] = r
cols[_idx] = c
arr = sparse.csr_matrix((data, (rows, cols)))
您寻找的显示很像 coo
稀疏矩阵的 str
显示。
In [216]: M = (sparse.random(5,5,.2)*10).astype(int)
In [217]: M
Out[217]:
<5x5 sparse matrix of type '<class 'numpy.int64'>'
with 5 stored elements in COOrdinate format>
In [218]: print(M) # str(M)
(0, 0) 0
(0, 2) 8
(1, 3) 8
(1, 4) 8
(4, 4) 4
稀疏矩阵有一个 nonzero
方法来显示非零元素的坐标。
In [219]: M.nonzero()
Out[219]: (array([0, 1, 1, 4], dtype=int32), array([2, 3, 4, 4], dtype=int32))
对于 coo
,值存储为 3 个数组:
In [220]: M.data, M.row, M.col
Out[220]:
(array([0, 8, 8, 8, 4]),
array([0, 0, 1, 1, 4], dtype=int32),
array([0, 2, 3, 4, 4], dtype=int32))
coo
格式中这些元素的顺序没有限制。甚至可以有重复项,尽管在转换为显示或 csr
格式时会将它们相加。
当我们将其转换为 lil
格式时,数据现在存储在 2 个列表数组中,每行一个列表:
In [221]: Ml = M.tolil()
In [222]: Ml.data
Out[222]:
array([list([0, 8]), list([8, 8]), list([]), list([]), list([4])],
dtype=object)
In [223]: Ml.rows
Out[223]:
array([list([0, 2]), list([3, 4]), list([]), list([]), list([4])],
dtype=object)
它也有nonzero
,但看代码(它使用coo
格式):
In [224]: Ml.nonzero()
Out[224]: (array([0, 1, 1, 4], dtype=int32), array([2, 3, 4, 4], dtype=int32))
In [225]: Ml.nonzero??
Signature: Ml.nonzero()
Source:
def nonzero(self):
...
# convert to COOrdinate format
A = self.tocoo()
nz_mask = A.data != 0
return (A.row[nz_mask], A.col[nz_mask])
File: /usr/local/lib/python3.6/dist-packages/scipy/sparse/base.py
Type: method
实际上,这是所有稀疏格式的通用 nonzero
。 nz_mask
部分允许矩阵可能有 0 个未被清理的值。
虽然 lil
旨在轻松逐个元素更新,但我们通常建议尽可能从 coo
样式的输入数组创建矩阵。通常可以更有效地创建这些数组。甚至列表追加或扩展也可以更快。
更多地关注 Ml
矩阵的迭代 - 它为每一行创建一个 lil
:
In [230]: [x for x in Ml]
Out[230]:
[<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 2 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 2 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 0 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 0 stored elements in List of Lists format>,
<1x5 sparse matrix of type '<class 'numpy.int64'>'
with 1 stored elements in List of Lists format>]
我们可以显示每一行的数据:
In [231]: [((i,x.rows[0]),x.data[0]) for i,x in enumerate(Ml)]
Out[231]:
[((0, [0, 2]), [0, 8]),
((1, [3, 4]), [8, 8]),
((2, []), []),
((3, []), []),
((4, [4]), [4])]
或过滤掉空行:
In [232]: [((i,x.rows[0]),x.data[0]) for i,x in enumerate(Ml) if x.data[0]]
Out[232]: [((0, [0, 2]), [0, 8]), ((1, [3, 4]), [8, 8]), ((4, [4]), [4])]
我们需要另一次迭代来分离每行中的元素。
关于稀疏数组与密集数组的使用,一条经验法则是稀疏度(非零元素的百分比)应小于 10% 才值得使用稀疏格式。但这在很大程度上取决于您的使用和关注。
从简单的数据存储角度来看,请注意 coo
格式必须为每个非零项使用 3 个数字,而不是密集数组仅使用 1 个数字。稀疏矩阵乘法对于 csr
格式比较好。其他可以只关注 data
值(例如 sin
)的计算也相对有效。但是如果数学必须比较2个矩阵的稀疏性,比如加法和element-wise乘法,稀疏的情况更糟。
索引、切片和求和实际上可能使用矩阵乘法。 coo
格式没有实现这些。 lil
可以很好地完成一些面向行的操作。创建稀疏矩阵的基本操作需要时间。