簡體   English   中英

在MATLAB中提取和存儲非零條目

[英]Extracting and storing non-zero entries in MATLAB

誰能幫助我建立和糾正我的代碼,該代碼旨在僅保存任意方陣及其索引的非零元素? 基本上,我需要編寫一個腳本,其功能與MATLAB中的“稀疏”功能相同。

`%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`

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

所以,

[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];

首先,建議不要使用內置的size函數,而不是將大小手動指定為n = 3

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

說得通?

因此,我認為我們已經確定,這樣做的目的是學習一種陌生的編程語言。 最簡單的解決方案是使用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(:);

我將使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM