Inserting zero rows and columns into matrix efficiently
3 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
I'm currently working on a project where I have a large set of matrices of varying size. Each matrix, A, has a vector, pointer, which corresponds to location information. I'm trying to get all the matrices into the same "space"; to achieve this, I am looking to create a "master" matrix, M, which has all the elements of A expanded to the larger matrix, which has location data for all matrices in the set. I have already created a master pointer, pointer_master, which contains the locations found in all matrices.
I'm trying to create two matrices using the original matrix, A, pointer, and pointer_master. The first matrix is the "occurrence" matrix, O, which shows you what elements from A appear in the large matrix M. I have already done this by using the function setdiff to find the missing elements
Code:
% This code compares pointer_master to pointer and creates
% a logical matrix O which sets all missing indices to 0.
pointer_master = 1:25;
pointer = [1 4 8 10 11 12 13 14 15 17 21 23 25];
[~, pointer_missingIndex] = setdiff(pointer_master,pointer);
O = true(length(pointer_master));
O(:,pointer_missingIndex) = false;
O(pointer_missingIndex,:) = false;
Here we have a pointer that is missing 12 elements from the master pointer. The code above creates a new large matrix O, with 0 in place of these missing elements. When this process is complete, I intend to sum these matrices to get the frequency of each element (I also want to average across elements using this matrix).
I'm having trouble figuring out how to create the master matrix. Unlike the occurence matrix, I need the elements of A to appear in M with all its elements. I can do this inefficiently, but I'm sure there is a better way to do this than what I have right now.
Code:
M = A;
for ii = 1:length(pointer_master)
X = find(pointer==pointer_master(ii), 1);
if(isempty(X))
column_insert = zeros(size(M,2),1); %#ok<NASGU>
row_insert = zeros(1,size(M,2)+1); %#ok<NASGU>
if(pointer_master(ii)<min(pointer))
column_insert = zeros(size(M,2),1);
row_insert = zeros(1,size(M,2)+1);
M = [logical(column_insert) M]; %#ok<AGROW>
M = [logical(row_insert); M]; %#ok<AGROW>
elseif(pointer_master(ii)>max(pointer))
column_insert = zeros(size(M,2),1);
row_insert = zeros(1,size(M,2)+1);
M = [logical(column_insert) M]; %#ok<AGROW>
M = [logical(row_insert); M]; %#ok<AGROW>
else
column_insert = zeros(size(M,2),1);
row_insert = zeros(1,size(M,2)+1);
M = [M(:,1:N) logical(column_insert) M(:,N+1:end)];
M = [M(1:N,:); logical(row_insert); M(N+1:end,:)];
end
else
N = ii;
end
end
I know this method is very inefficient, especially for matrices with 20,000+ elements, so I'm trying to figure out how to do this faster. I can use ismember to output a vector that tells you where pointer falls in pointer_master. but I don't know how to get the elements from A into M.
Code:
[~,X] = ismember(pointer_master,pointer);
Does anyone have any experience with this? Thanks.
For example:
A = [1 2 3; 4 5 6; 7 8 9];
pointer = [1 3 4];
pointer_master = 1:5;
My occurrence matrix would be:
O = [1 0 1 1 0; 0 0 0 0 0; 1 0 1 1 0; 1 0 1 1 0; 0 0 0 0 0];
My master matrix M would be:
M = [1 0 2 3 0; 0 0 0 0 0; 4 0 5 6 0; 7 0 8 9 0; 0 0 0 0 0];
3 Kommentare
Akzeptierte Antwort
Andrei Bobrov
am 7 Mai 2012
A = [1 2 3; 4 5 6; 7 8 9];
pointer = [1 3 4];
pointer_master = 1:5;
p = ismember(pointer_master,pointer);
M = bsxfun(@and,p,p')+0;
M(M~=0)=A;
0 Kommentare
Weitere Antworten (3)
Richard Brown
am 7 Mai 2012
Perhaps I'm misunderstanding, but your example can be generated from the following
M = zeros(numel(pointer_master));
M(pointer,pointer) = A;
If the number of elements in pointer is much fewer than the number of elements of pointer_master, you may well want to use a sparse matrix:
n = numel(pointer_master);
[I, J] = ndgrid(pointer);
M = sparse(I, J, A, n, n);
Jan
am 7 Mai 2012
I do not understand what you are looking for. But I have a general advice when I see "%#ok<AGROW>". Don't do this. Either pre-allocate the required size and fill in the data afterwards. Or pre-allocate to much memory and cut off the unneeded part at the end.
This wastes time also:
column_insert = zeros(size(M,2),1);
row_insert = zeros(1,size(M,2)+1);
M = [M(:,1:N) logical(column_insert) M(:,N+1:end)];
At first "false()" is faster than "logical(zeros())". But I assume this would be even faster:
M(:, N+2:end+1) = M(:,N+1:end);
M(:, N+1) = 0;
I have the impression that you mix DOUBLEs and LOGICALs in the matrix M. If so, don't do it.
0 Kommentare
Effrom
am 7 Mai 2012
2 Kommentare
Richard Brown
am 8 Mai 2012
Glad to hear you got it sorted. I'm puzzled as to why the bsxfun version works differently for you - on my system both methods use exactly the same amount of memory (the amount of memory required to store both A and M as doubles).
Siehe auch
Kategorien
Mehr zu Matrix Indexing finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!