Given a table of data and number of occurrences, can I create the underlying dataset?

114 views Asked by At

I have a 2-column matrix that describes a piece of data, and the number of times that data occurred within a set:

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

Given that, is there an "elegant" way to produce the underlying dataset? i.e.,

B = [1 1 1 1 1 1 2 2 3 3 3 3 3 3 3 3 4 5 5 5];                                       

There are plenty of ways to go from B to A (tabulate, using unique and histc, etc) but I couldn't find any way to go from A to B. The best I could do is not elegant:

B = [];
for ii = 1:size(A,1)
    B = [B repmat(A(ii,1), 1, A(ii,2))];
end

I have a sneaking suspicion the "correct" way to do this is to use bsxfun or accumarray, but I am not experienced enough to understand how these really work.

5

There are 5 answers

0
H.Muster On BEST ANSWER

You can use 'arrayfun' in combination with 'cell2mat':

 B = cell2mat(arrayfun(@(x,y) ones(y,1)*x, A(:,1), A(:,2), 'uniformoutput', false))'

This results in

B =

  Columns 1 through 16

     1     1     1     1     1     1     2     2     3     3     3     3     3     3     3     3

  Columns 17 through 20

     4     5     5     5
0
Mohsen Nosratinia On

Here is a solution using bsxfun:

B = A(1+sum(bsxfun(@lt, cumsum(A(:,2)), 1:sum(A(:,2)))), 1).';
0
Ilya Kobelevskiy On

Not super elegant either, but this may work:

B = {A(:,1)*ones(1,A(:,2)};
B = [B{:}];

Have no matlab to check syntax, idea is to remove loop from

B=[];
for ii=1:size(A,1)
   B=[B A(i,1)*ones(1,A(i,2)];
end;
0
shoelzer On

Here's one more option. I wouldn't call it elegant, but it's pretty efficient.

ndx = cumsum([1; A(:,2)]);
B = zeros(1, ndx(end)-1);
B(ndx(1:end-1)) = 1;
B = A(cumsum(B), 1).';
0
P0W On

This is similar to H.Muster post

using repmat

B=cell2mat(arrayfun(@(x,y)(repmat(x,y,1) ), A(:,1), A(:,2), ...
                                   'UniformOutput', false));

B' is expected output.