2010-04-15 96 views
0

我有一个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 S和-0.6,第二01.8,第三-2.3等。

在这种情况下,我想,以减少米至1(获得从给定矩阵向量),因此在本例中,载体可以[-0.6 1.8 -2.3 3.4 -3.8 -4.3]

有谁知道什么是让从载体的最佳方式这样的矩阵?

谢谢!

+0

@niko:我建议你更清楚地解释您的具体目标是什么,因为你可以质疑不同的解释。我想知道我是否需要开始道歉。 – Jonas 2010-04-15 15:01:20

回答

1

这里的一个单行使用该函数SUM

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

这将返回一个包含从每列中的重复的非零值的1乘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 
+0

如何“非惯用”!但是比我的版本更短,更聪明。 +1 – Jonas 2010-04-15 16:00:19

0

M = M(M~=0)

M(find(M))

,并请学习如何为SO读者格式化代码。

编辑@Jonas表明,OP想从M.每个非零元素的唯一一个出现为了得到这个尝试包裹前述任何建议,unique(),如

unique(M(M~=0)) 
0

这实际上不是一个稀疏矩阵。 MATLAB中的稀疏矩阵就是这样定义的。如果使用稀疏或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 

看到我用过了。做转置,以防万一任何元素都很复杂。

+1

如果我理解正确的问题,这不是@niko正在寻找的。 – Jonas 2010-04-15 14:01:33

+0

这不是niko想找什么?这会返回一个带有非零元素的向量,完全按照请求的顺序。唯一的区别是我没有将结果转换为行向量。但只有一个“矢量”被要求。如果OP真的想要一个行向量,那么。'将转换成一个。 如果OP有这个问题暗示的其他模糊方案,那么他需要明确提出这个问题,这比现在要清楚得多。 – 2010-04-15 14:31:01

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 
+0

这是一种非常复杂的方式,它为自然的Matlab成语做了一些事情! – 2010-04-15 13:41:23

+0

@高性能标记:你和@woodchips的解决方案找到了多个版本的数值,这不是OP所要求的,据我了解。我不认为这个版本太复杂了。你可能会用两个输出来运行find,并且每行只取一个数值,但是这会涉及更多的输入。 – Jonas 2010-04-15 13:59:47

+0

@Jonas:看到我上面的编辑。我仍然认为你的方法是单一的,太过复杂。 – 2010-04-15 14:24:46

0

如果OP真的想要找到也是唯一的非零元素,那么比Jonas建议的方法要好得多。

合乎逻辑的解决方案是找到非零元素FIRST。然后应用独特的功能。所以这样做:

unique(M(find(M))) 

如果你的目标是找到特定的顺序这些元素,那么订单需要在你的目标明确定义。

+0

我认为他提供的解决方案是目标。 – Jonas 2010-04-15 14:50:01

+0

最后,我们三人同意! – 2010-04-15 14:52:38

+1

其实我们没有,因为我认为订单很重要:)。 – Jonas 2010-04-15 15:02:55