How to use a vector as indices for matrix?

46 Ansichten (letzte 30 Tage)
Hagai
Hagai am 1 Dez. 2014
Bearbeitet: Hagai am 2 Dez. 2014
Hi,
Let's say I have a matrix NxM , and i have a vector 1xM. the contents of the vector indicates for every column in which row i should put the value '1'.
example - 5x5 matrix A all zeros, and vector V 1x5 = [3 1 1 5 4]. I want to get:
0 1 1 0 0
0 0 0 0 0
A = 1 0 0 0 0
0 0 0 0 1
0 0 0 1 0
How can I do that without using loops? (my matrix size is very large)
Thanks

Akzeptierte Antwort

Azzi Abdelmalek
Azzi Abdelmalek am 1 Dez. 2014
Bearbeitet: Azzi Abdelmalek am 1 Dez. 2014
V= [3 1 1 5 4]
m=numel(V);
n=max(V)
idx=sub2ind([n m],V,1:m)
out=zeros(n,m)
out(idx)=1

Weitere Antworten (2)

Image Analyst
Image Analyst am 1 Dez. 2014
Bearbeitet: Image Analyst am 1 Dez. 2014
How large is large to you? And, a for loop is not always slow. Look at my code where I have a matrix of 100 thousand rows and 100 thousand columns. Is your matrix larger than that? The elapsed time was 0.071 seconds - only 71 milliseconds for a pretty big array. How fast do you need it to be?
A = zeros(100000, 'uint8');
[rows, columns] = size(A)
numel(A)
V = randi(rows, 1, columns);
tic;
for k = 1 : columns
A(V(k), k) = 1;
end
toc;
  3 Kommentare
Image Analyst
Image Analyst am 2 Dez. 2014
How many elements are in each signal?
I see you accept Azzi's code but I couldn't get Azzi's code to work at first - it had an out of memory error even though I have 32 GB of RAM. I discovered the problem. You need to tell zeros to user 'uint8'. Or else you can use false() instead of zeros(). I guess you must have discovered the same thing because you said you got it to work. If you make that correction his code is 0.009 seconds faster (on my slow home computer) for an array of 10 billion elements.
I couldn't get Andrei's code to work at all because accumarray makes a double and I didn't know how to get it to work with logical or uint8 arrays.
clc; % Clear the command window.
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
% My code - works!
A = zeros(100000, 'uint8');
[rows, columns] = size(A)
numel(A)
V = randi(rows, 1, columns);
tic;
for k = 1 : columns
A(V(k), k) = 1;
end
toc;
clear('A');
% Andrei's code - out of memory
% tic;
% n = numel(V);
% A = accumarray([V(:) (1:n)'],1,[max(V) n]);
% toc;
% clear('A');
% Azzi's code - out of memory unless corrected
tic
m=numel(V);
n=max(V);
idx=sub2ind([n m],V,1:m);
out=zeros(n,m, 'uint8'); % NEED TO CHANGE TO UINT8!
out(idx)=1;
toc
Hagai
Hagai am 2 Dez. 2014
Bearbeitet: Hagai am 2 Dez. 2014
I have tested all three answers, indeed yours has better run time then Andrei's, but Azzi's solution is the fastest. I don't have memory issues at the moment, but thanks for the idea of logic matrix, I will use it for this is only preliminary algorithm.
As for how big the matrices are - about the same size as you have given.

Melden Sie sich an, um zu kommentieren.


Andrei Bobrov
Andrei Bobrov am 1 Dez. 2014
n = numel(V);
A = accumarray([V(:) (1:n)'],1,[max(V) n]);

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by