我有一个布尔值的起始lil_array
。(Docs)
例如尺寸3,5和数值:
(0, 2) True
(0, 4) True
(1, 0) True
(1, 1) True
(1, 3) True
(2, 0) True
(2, 3) True
字符串
所以这是一个类似于下面的矩阵(True表示为1):
0 0 1 0 1
1 1 0 1 0
1 0 0 1 0
型
我也有一个np.ndarray,它的大小与用Int值填充的行的大小相同。对于这个例子,我将使用以下内容:
arr = np.array([0, -1, 0, 3, 2])
型
我想生成下面的lil_array(当然,零不会保存在稀疏数组中):
0 0 0 0 2
0 -1 0 3 0
0 0 0 3 0
型
其中每行是初始LIL_array对应行与arr
的逻辑与。
我知道如何用几种方法来实现这一点,首先将lil_array转换为矩阵,或者将行转换为ndarray或列表,但这会降低利用该矩阵的稀疏属性所获得的效率。(这是一个玩具示例,但我的问题涉及一个更大的矩阵)
如何在不将稀疏矩阵转化为矩阵的情况下,以有效和干净的方式生成输出?
3条答案
按热度按时间zzzyeukh1#
首先,如果你主要关心的是内存效率,我会引导你远离lil_array。LIL在内部使用列表,而Python are not very memory efficient中的列表。lil_array主要是在你想创建一个稀疏数组但不知道它将有多少非零元素时有用。我会引导你转向COO或CSR。
第二,您要查找的实际上是
np.where(boolean_array, arr, 0)
,除了您希望它在稀疏数组上工作而不首先将它们转换为非稀疏数组。在google上搜索“scipy sparse where”可以找到this thread,这几乎就是我们需要的代码。
where1
函数几乎就是我们需要的,除了它假设它索引的第二个数组是2D稀疏数组,而你拥有的是1D密集数组。我们可以通过删除对.tocsr()
的调用来解决这个问题,并且只按列索引。代码:
字符串
(如果您希望结果以lil格式显示,请取消注解
zs = zs.tolil()
。)根据基准测试,这比@Malcolm对100000 x10000矩阵(0.1%非零元素)的回答快100倍。
axr492tv2#
我建议不要将原始数组存储为lil_array。相反,只需存储与真实值对应的元组列表。或者如果您已经将其存储为lil_array,则使用
lil_array.nonzero
方法将其转换为索引列表。然后使用这些元组填充lil_array中的值作为结果。字符串
ocebsuys3#
最简单的代码-如果稀疏矩阵实际上是稠密的
字符串
如果矩阵不是太大(即没有内存错误),那么很容易在稀疏和密集之间转换:
型
我开始的时候很密集:
型
请注意,通常
lil
用于迭代构造矩阵。coo
更适合从[48]中所示的坐标进行构造。csr
最适合计算。sparse
很容易在这些选项之间转换。(toarray()
通常通过csr格式创建)。lil值存储为两个对象dtype数组-每个数组包含代表每行的列表:
型
同样,这种格式很容易迭代修改,但不是最紧凑或计算上最方便的。
在进一步的编辑中,我将探索从
M
创建你想要的Map,虽然很容易在M
的行上进行操作(甚至还有一个getrowview
),但rwo和arr
之间的逻辑和并不明显。下面是一种迭代lil的行的方法
型
换句话说,使用
rows
列表索引arr
,并将这些值(作为列表)赋回M
。由于
arr
有一些0值,这些值将出现在新的M
中:型
去掉这些0还需要修剪
rows
属性。也可以在
csr
的行上进行扩展,这样可能会更快,尽管在概念上更复杂。