从稀疏矩阵中获取向量的最佳方法

时间:2010-04-15 12:10:49

标签: matlab sparse-matrix

我有一个m x n矩阵,其中每一行由零和每行的相同值组成。

一个例子是:

M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0]

在此示例中,第一列包含0-0.6,第二列01.8,第三列-2.3等等。

在这种情况下,我想将m减少到1(从给定矩阵中获取一个向量),所以在这个例子中,向量将是[-0.6 1.8 -2.3 3.4 -3.8 -4.3]

有谁知道从这样的矩阵中获取矢量的最佳方法是什么?

谢谢!

5 个答案:

答案 0 :(得分:1)

如果存在未知数量的非零和零,解决问题的一种方法是首先用NaN替换零,然后使用max或min之类的东西来查找数据。

%# create an array
M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0];

%# replace zeros with NaN
M(M==0) = NaN;

%# get, for each column, the number
numbers = max(M,[],1)

numbers =

    -0.6000    1.8000   -2.3000    3.4000   -3.8000   -4.3000

修改

这就是我理解这个问题的方法: “我希望,对于每一列,都要知道非零条目的值。每列只有一个非零数字,但它可能会多次出现”

这是一种更类似Matlab(但更长)的方法来获得解决方案:

%# create an array
    M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0];

%# find the non-zero entries
[r,c] = find(M);

%# only take one entry per column
[uniqueCols, sortIdx] = unique(c);

%# fix the rows correspondingly
uniqueRows = r(sortIdx);

%# convert to index
idx = sub2ind(size(M),uniqueRows,uniqueCols);

%# get the numbers per column (transpose as needed)
numbers = M(idx)

numbers =

   -0.6000
    1.8000
   -2.3000
    3.4000
   -3.8000
   -4.3000

答案 1 :(得分:1)

这是一个使用函数SUM的单行程序:

nonZeroColumnValues = sum(M)./sum(M ~= 0);

这将返回1-by-n向量,其中包含每列的重复非零值。它通过对每列求和,然后将结果除以每列中的非零值的数量来实现。如果列中没有非零值,则该列的结果将为NaN

以下是使用问题中的示例矩阵M的示例:

>> M = [-0.6 1.8 -2.3 0 0 0; 0 0 0 3.4 -3.8 -4.3; -0.6 0 0 3.4 0 0]

M =

   -0.6000    1.8000   -2.3000         0         0         0
         0         0         0    3.4000   -3.8000   -4.3000
   -0.6000         0         0    3.4000         0         0

>> nonZeroColumnValues = sum(M)./sum(M ~= 0)

nonZeroColumnValues =

   -0.6000    1.8000   -2.3000    3.4000   -3.8000   -4.3000

答案 2 :(得分:0)

M = M(M~=0)

M(find(M))

请学习如何格式化SO读者的代码。

EDIT @Jonas建议OP只希望M中的每个非零元素出现一次。要尝试在unique()中包含上述任何一个建议,例如

unique(M(M~=0))

答案 3 :(得分:0)

这实际上不是稀疏矩阵。 MATLAB中的稀疏矩阵就是这样定义的。如果使用sparse或spdiags函数来定义该矩阵,则不需要存储零元素,只需要存储非零元素。当然,MATLAB知道如何与其他标准双数组一起使用这些真正的稀疏矩阵。

最后,真正的稀疏矩阵通常比这稀疏得多,或者你根本不打算使用稀疏存储形式。

无论如何,如果您只想要任何矩阵的非零元素,那么您可以这样做:

NZ = M(M ~= 0);

或者,

NZ = M(find(M));

要么按列字符串输出非零值,因为这就是数字在MATLAB中存储在矩阵中的方式。

NZ = M(find(M))
NZ =
         -0.6
         -0.6
          1.8
         -2.3
          3.4
          3.4
         -3.8
         -4.3

在您的问题中,您询问了如何按行执行此操作,提取第一行中的非零元素,然后提取第二行等等。

最简单的方法是首先转置数组。因此,我们可能会做类似......

NZ = M.';
NZ = NZ(find(NZ))
NZ =
         -0.6
          1.8
         -2.3
          3.4
         -3.8
         -4.3
         -0.6
          3.4

看到我用过的。进行转置,以防任何元素都很复杂。

答案 4 :(得分:0)

如果OP真的想要找到同样独特的非零元素,那么有更好的方法可以做到这一点,而不是Jonas建议的。

逻辑解决方案是首先找到非零元素。然后应用唯一的功能。所以这样做:

unique(M(find(M)))

如果您的目标是按特定顺序查找这些元素,则需要在目标中明确定义该顺序。