Guy Wald
Guy Wald

Reputation: 599

Matlab: Getting Random values from each column w/o zeros

I have a 2d matrix as follows:

possibleDirections =

 1     1     1     1     0
 0     0     2     2     0
 3     3     0     0     0
 0     4     0     4     4
 5     5     5     5     5

I need from every column to get a random number from the values that are non-zero in to a vector. The value 5 will always exist so there won't be any columns with all zeros. Any ideas how this can be achieved with the use of operations on the vectors (w/o treating each column separately)? An example result would be [1 1 1 1 5]

Thanks

Upvotes: 3

Views: 183

Answers (3)

H.Muster
H.Muster

Reputation: 9317

Alternative solution:

[r,c] = size(possibleDirections);

[notUsed, idx] = max(rand(r, c).*(possibleDirections>0), [], 1);

val = possibleDirections(idx+(0:c-1)*r);

If the elements in the matrix possibleDirections are always either zero or equal to the respective row number like in the example given in the question, the last line is not necessary as the solution would already be idx.

And a (rather funny) one-liner:

result = imag(max(1e05+rand(size(possibleDirections)).*(possibleDirections>0) + 1i*possibleDirections, [], 1));

Note, however, that this one-liner only works if the values in possibleDirections are much smaller than 1e5.

Upvotes: 2

grantnz
grantnz

Reputation: 7423

You can do this without looping directly or via arrayfun.

[rowCount,colCount] = size(possibleDirections);
nonZeroCount = sum(possibleDirections ~= 0);
index = round(rand(1,colCount) .* nonZeroCount +0.5);
[nonZeroIndices,~] = find(possibleDirections);
index(2:end) = index(2:end) + cumsum(nonZeroCount(1:end-1));
result = possibleDirections(nonZeroIndices(index)+(0:rowCount:(rowCount*colCount-1))');

Upvotes: 2

yuk
yuk

Reputation: 19870

Try this code with two arrayfun calls:

nc = size(possibleDirections,2); %# number of columns
idx = possibleDirections ~=0;    %# non-zero values
%# indices of non-zero values for each column (cell array)
tmp = arrayfun(@(x)find(idx(:,x)),1:nc,'UniformOutput',0); 
s = sum(idx); %# number of non-zeros in each column
%# for each column get random index and extract the value
result = arrayfun(@(x) tmp{x}(randi(s(x),1)), 1:nc); 

Upvotes: 1

Related Questions