我在MATLAB中有一个矩阵,我想确定哪一行包含最多的零。也就是说,我想找到矩阵中最稀疏的行(和列(。有没有比使用mat(sum(mat==0,i)==i,:)
循环更有效的方法?还是这是首选方法?
我用它来实现LU因子分解,通过使用"最小度排序启发式"来求解线性系统。
如果我正确解释了这一点,那么要找到"最稀疏"的行,就意味着要找到零个数最多的行。您可以以矢量化的方式将sum
与max
结合使用来计算:
[~, row] = max(sum(mat == 0, 2));
mat == 0
将把整个矩阵转换为true/false
,使true
为零值,否则为false
,然后我们单独使用sum
并对每行求和。这将减少问题,使每个元素计算出每行遇到的零元素数量。在该结果上使用max
的第二个输出,row
将因此包含具有最大数量的零的行。我们忽略第一个输出,因为这将输出实际的最大值,考虑到您的问题,我们不在乎。
如果您关心速度,可以将转换后的true/false
矩阵与向量ones
进行矩阵向量乘法运算。通过这种方式,它将为您执行求和,从而将矩阵提升为double
精度:
[~, row] = max((mat == 0)*ones(size(mat, 2), 1)));
次要注释
请注意,如果有多行共享相同数量的最大零,则此方法的局限性在于它将返回满足此条件的第一个行。就你的目标而言,我认为这就足够了。还要注意,如果矩阵包含无零,则此方法的输出将默认为第一行。有一些角落的情况我没有考虑在内,但我不确定你需要在多大程度上检查这些情况,所以为了简单起见,我将把它们排除在外。
我不知道有哪个函数可以以矢量化的方式实现这一行操作(也就是说,直到我看到rayryeng的巧妙解决方案(,但在nnz
上循环应该相当快。循环不再很慢,因为新发动机推出了R2016a。
tmp = zeros(size(mat,1),1);
for ii = 1:size(mat,1)
tmp(ii) = nnz(mat(ii,:));
end
附带说明:我反对使用i
作为变量,因为它表示虚单位。