![](/img/trans.png)
[英]For large sparse matrices in MATLAB, compute the cumulative sum across the columns for non-zero entries?
[英]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]
接下來,要初始化數組RI
, CI
和V
我們想知道它們的大小。 由於我們不知道從零開始的非零元素的數目,因此有兩個選擇:(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
,可以類似地使用它。
現在,我們可以去你開始使用同樣的路線:程序for
和if
在每一行和每一列。 幾乎可以是任何一種編程語言,但也有一些標點符號的怪癖。 但是,即使您確實糾正了錯誤(例如, 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.