Alexander V.
Alexander V.

Reputation: 68

MATLAB / Octave : Increment array with an array of indexes

I am struggling to optimize a piece of code. I will have to deal with many numbers (millions) and my code is running slow. Let's suppose that we have the matrix 3x3:

A = [ 8 1 6; 3 5 7; 4 9 2 ];

I want to know how many elements are in the intervals [0, 3), [3, 6) and [6, 9). Therefor, i need a matrix 1x3 :

p = [ 2 3 4 ];

My code is :

p = zeros(1, 3);
for i = 1 : 9
   p( floor(A / 3) + 1 ) += 1;

I want to do it without for loops, but the code :

p = zeros(1, 3);
p( floor(A / 3) + 1 ) += 1;

Outputs :

p = 1 1 1

Any ideas why? And how can i correct this issue?

Upvotes: 3

Views: 551

Answers (2)

Daniel
Daniel

Reputation: 36710

What you are implementing is a histogram:

p=histc(A(:),[0,3,6,9]); %For MATLAB 2014b or newer use histcounts instead

It returns p=[2,3,3,1] because it implicitly creates an interval [9,inf)

To explain the indexing problem. Multiple assignments to the same index are not supported in MATLAB. They always take the last assignment:

x=zeros(3,1)
x([1,1,2,1])=[1,2,3,4] %results in x(1)=4

And for the increment operator, the same rules apply. It behaves like:

x([1,1,1,1])=x([1,1,1,1])+1

For the general case of such an multi-assignment, you can use accumarray:

%assume you want x([1,1,2,1])=[1,2,3,4]
accumarray([1,1,1,1].',[1,2,3,4].')
%results in [7,3]

Upvotes: 2

dfrib
dfrib

Reputation: 73176

Histogram bin counts

As Daniel writes in his answer, you're computing counts of values in histogram bins. An alternative method to hist is using the newer histcounts command (recommended for newer Matlab versions).

A = [ 8 1 6; 3 5 7; 4 9 2 ];
[p, ~, ~] = histcounts(A, 0:3:9);

%// p = 2     3     4

Matrix relation operators followed by non-zero element count

You could also make use of matrix relational operators followed by nnz command to count non-zero elements:

A = [ 8 1 6; 3 5 7; 4 9 2 ];
p = [nnz(A < 3);
    nnz(A >= 3 & A < 6);
    nnz(A >= 6)];         %// alternatively nnz(A >= 6 & A < 9) for the last entry

%// ...

p =

     2
     3
     4

"Quickest?"

From some quick tic/toc tests, it seems that—on my system (running Matlab R2014b)—the latter nnz method is:

  • ~3-4 times quicker than the histcounts method.
  • ~5-6 times quicker than the histogram method using the older hist command.

I have not tried, however, to see how this scales as A becomes larger, in case this is the case for your application.

Upvotes: 1

Related Questions