0

Can anyone tell me how vectorize the following:

a = randi([6 10],5);; 
c = unique(a);
d = [1:5]; % some comparison Values length should be equal to length(c)

Mat = zeros(size(a));
for i = 1:length(c)
  Mat(a==c(i)) = d(i);
end

Result:

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

Here 6 is replaced by 1, 7 is replaced by 2, etc.

This is of course just an example; my real Mat is more like 2000×2000.

2
  • I started formulating an answer with the old version of your question; the new version seems a lot simpler actually :) Ah well, I think it's enough to get you going. Commented Feb 12, 2014 at 8:57
  • Well, it was indeed so simple, that I just planted another answer. Commented Feb 12, 2014 at 9:08

2 Answers 2

2

NOTE: read my other answer first

To answer the question in your latest edit:

[~, inds] = histc(a(:), c);
Mat = reshape(d(inds), size(a));

Doing a similar test for 600×100 data:

a = randi(500,[600 100]); 
c = unique(a);
d = randi(20, size(c));

tic
Mat = zeros(size(a));
for ii = 1:length(c)
  Mat(a==c(ii)) = d(ii);
end
toc


tic
[~, inds] = histc(a(:), c);
Mat2 = reshape(d(inds), size(a));
toc

isequal(Mat,Mat2)

Gives the following:

Elapsed time is 0.166673 seconds.  %// your method
Elapsed time is 0.006669 seconds.  %// my method
ans =                              %// yes they're equal
    1

The speeds again differ by a factor of ~250.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 great! I didn't know about the second output of histc, it seems to be usefull.
0

NOTE: this is an answer to the original question; the second edit changed the question completely, so the answer below no longer applies. The edit greatly simplifies the problem, so this answer is still a good place to start.

Basically, all unique values of a will be replaced by corresponding values in b. That implies the matrix to analyze is b, and the only difficulty lies in the fact that the condition b < d must hold for corresponding indices in b.

To do this, you can simply bin all elements of a in groups defined by c and determine what group each element in b belongs to. That information can be used to find the proper indices in d.

In other words:

NewMat = b;
[~, inds] = histc(a(:), c);
NewMat(NewMat(:) > d(inds)) = 0;

A small test to compare the performance and validate the equality of the two methods:

a = randi(1000, 74,100);
b = randi(1000, 74,100);

c = unique(a);
d = randi(1000, size(c)); % some comparison Values

%// Your method
tic
NewMat = zeros(size(a));
for i = 1:length(c)
  Mat = zeros(size(a));
  Mat(a==c(i)) = b(a==c(i));
  Mat(Mat > d(i)) =0;
  NewMat = NewMat + Mat;
end
NewMat1 = NewMat;
toc

%// My method
tic
[~,inds] = histc(a(:), c);
b(b(:) > d(inds)) = 0;
NewMat2 = b;
toc

%// validate solution
isequal(NewMat1, NewMat2)

Results:

%// 74 × 100
Elapsed time is 0.151808 seconds.   %// your method 
Elapsed time is 0.001007 seconds.   %// my method
ans =                               %// yes, they're equal
     1

So a factor of ~150 performance increase. Using not 74×100 but 740×1000 gives

%// 740 × 1000
Elapsed time is 27.587543 seconds.  %// your method
Elapsed time is 0.111467 seconds.   %// my method
ans =                               %// yes, they're equal
     1

or a factor of ~250 difference. So apparently, your method also scaled worse than the histc approach.

2 Comments

@user2851655: also see my other answer, which answers your question as it currently is.
@user2851655: you're welcome; I enjoy these kinds of puzzles, so it was my pleasure really :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.