Имея таблицу данных и количество вхождений, могу ли я создать базовый набор данных?

У меня есть матрица с двумя столбцами, которая описывает часть данных и количество раз, когда эти данные встречаются в наборе:

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

Учитывая это, существует ли «элегантный» способ создания базового набора данных? т.е.

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

Существует множество способов перейти с B на A (tabulate, используя < a href = "https://stackoverflow.com/questions/5385651/determining-the-number-of-occurrences-of-each-unique-element-in-a-vector"> unique и histc и т. д. ), но я не мог найти способ перейти с A на B. Лучшее, что я мог сделать, не элегантно:

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

У меня есть скрытое подозрение, что «правильный» способ сделать это - использовать bsxfun или accumarray, но у меня недостаточно опыта, чтобы понять, как они действительно работают.


person Dang Khoa    schedule 10.09.2013    source источник


Ответы (5)


Вы можете использовать arrayfun в сочетании с cell2mat:

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

Это приводит к

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
person H.Muster    schedule 10.09.2013

Вот еще один вариант. Я бы не назвал это элегантным, но довольно эффективным.

ndx = cumsum([1; A(:,2)]);
B = zeros(1, ndx(end)-1);
B(ndx(1:end-1)) = 1;
B = A(cumsum(B), 1).';
person shoelzer    schedule 10.09.2013

Не очень элегантно, но это может сработать:

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

Нет Matlab для проверки синтаксиса, идея состоит в том, чтобы удалить цикл из

B=[];
for ii=1:size(A,1)
   B=[B A(i,1)*ones(1,A(i,2)];
end;
person Ilya Kobelevskiy    schedule 10.09.2013

Вот решение с использованием bsxfun:

B = A(1+sum(bsxfun(@lt, cumsum(A(:,2)), 1:sum(A(:,2)))), 1).';
person Mohsen Nosratinia    schedule 10.09.2013

Это похоже на сообщение Х.Мустера

используя repmat

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

B' - ожидаемый результат.

person P0W    schedule 10.09.2013