在MATLAB中提取和存储非零项

时间:2017-02-03 21:13:31

标签: matlab

任何人都可以帮我构建和更正我的代码,目的只是保存任意方阵和其索引的非零元素吗?基本上我需要编写一个与MATLAB中的'sparse'功能相同的脚本。

`%Consider a 3x3 matrix
A=[ 0 0 9 ;-1 8 0;0 -5 0 ];
n=3; %size of matrix

%initialise following arrays:
RI= zeros(n,1); %row index
CI = zeros(n,1); %column index
V = zeros(n,1); %value in the matrix
for k = 1:n %row 1 to n
    for j = 1:n %column 1 to n
      if A(k,j)~=0
        RI(k)=k;
        CI(j)=j;
        V(k,j)=A(k,j);
      end
    end 
end`

3 个答案:

答案 0 :(得分:0)

您可以使用find function查找所有非零元素。

所以,

[RI, CI, V] = find(A);
%      2     1    -1
%      2     2     8
%      3     2    -5
%      1     3     9

编辑:

我从您的评论中意识到您的目标是在Matlab中学习编码,您可能想知道为什么您的代码没有按预期工作。因此,让我尝试解释该问题以及与您类似的示例代码。

% Given:

A = [0 0 9; -1 8 0; 0 -5 0];

首先,我建议不要手动指定尺寸为n = 3,而是建议使用内置的size功能。

sz = size(A); 
% note that this contains 2 elements: 
%    [number of rows, number of columns]

接下来,要初始化数组RICIV,我们想知道它们的大小。由于我们不知道要开始的非零元素的数量,我们 有两个选项:(1)选择一个保证等于或大于非零元素数的大数,例如prod(sz)。 (为什么这是真的?)。 (2)根本不要初始化它,让Matlab根据需要动态分配内存。我按照下面的代码中的第二个选项进行操作。

% we'll keep a count of non-zero elements as we find them
numNZ = 0; % this will increment every time a non-zero element is found
for iCol = 1:sz(2) %column 1 to end
    for iRow = 1:sz(1) %row 1 to end
      if A(iRow,iCol)~=0
          numNZ = numNZ + 1;
          RI(numNZ) = iRow;
          CI(numNZ) = iCol;
          V(numNZ)  = A(iRow,iCol);
      end
    end 
end

disp([RI, CI, V])
%      2     1    -1
%      2     2     8
%      3     2    -5
%      1     3     9

有道理吗?

答案 1 :(得分:0)

所以我认为我们已经确定了这一点,就是学习一种不熟悉的编程语言。最简单的解决方案是使用sparse本身,但这使您无法深入了解编程。 find也不能,可以类似地使用。

现在,我们可以使用您开始使用的相同路线:每行和每列的程序forif。可能几乎是任何编程语言,但有一些标点符号的怪癖。但是你所发现的,即使你确实纠正了错误(比如n应该是非零条目的数量,而不是行数),这是一种非常缓慢的方式在Matlab中做数值工作。

这是另一种(效率仍然低效,但不那么有效)的方式,希望能够提供一些对矢量化的信息。做事方式,这是让Matlab变得如此强大的事情之一:

function [RI, CI, V] = mysparse(A)       % first:   use functions!


[nRows, nCols] = size(A);
[allRowIndices, allColIndices] = ndgrid(1:nRows, 1:nCols)   % let's leave the semicolon off so you can see for yourself what it does.
                                                            % It's very similar to `meshgrid` which you'll see more often (it's heavily used in Matlab graphics)
                                                            % but `ndgrid` is "simpler" in that it's more in tune with the fundamental conventions of Matlab (rows, then columns)

isNonZero = A ~= 0;   % this gives you a "logical array" which is a very powerful thing: it can be used as a subscript to select elements from another array, in one shot...

RI = allRowIndices(isNonZero);  % like this
CI = allColIndices(isNonZero);  % or this
V = A(isNonZero);               % or even this

RI = RI(:);  % have to do this explicitly, because the lines above will reshape the values into a single long string under some circumstances but not others
CI = CI(:);
V = V(:);

答案 2 :(得分:0)

我将使用N x 3矩阵,其中N是矩阵中非零元素的数量。

% Define a matrix A as follows:
A = randi([0 1],[4 4])
for i=1:16
   if A(i) ~= 0
      A(i) = rand;
   end
end

[row,col] = find(A);
elms = A(A~=0);  % MATLAB always works in column-major order and is consistent, 
                 % so no need to use sub2ind to access elements given by find

newSparse_A = [row col elms];

输出:

newSparse_A =

1.0000    1.0000    0.9027
2.0000    1.0000    0.9448
3.0000    1.0000    0.4909
1.0000    2.0000    0.4893
2.0000    2.0000    0.3377
4.0000    2.0000    0.9001

>> sparse(A)

ans =



   (1,1)       0.9027
   (2,1)       0.9448
   (3,1)       0.4909
   (1,2)       0.4893
   (2,2)       0.3377
   (4,2)       0.9001