There is a similar question here, Element-wise array replication in Matlab, but I'd like to generalize it slightly. The simple case wants a function 'replicate' which would take a vector, a, and then replicate each element by a number N. E.g.
>> a = [1, 2, 3];
>> replicate(a, 3);
ans =
[1, 1, 1, 2, 2, 2, 3, 3, 3]
>>
There are a number of solutions in the above link which are helpful. However, what happens with N is a vector of multiplicities for each element? E.g., I would like something like:
>> a = [1, 2, 3];
>> N = [3, 1, 5];
>> replicate(a,N)
ans =
[1, 1, 1, 2, 3, 3, 3, 3, 3]
>>
Unfortunately, my MATLAB-index-fu isn't quite to this level, and I can't figure out how to do this without looping over, say, N, and then using repmat to tile each element of a into a size [N(i),1] vector. E.g. where I loop over the array data, and then repmat it using the multiplicity value in multcol position. Data is steps in a MCMC, and the multiplicity of each step is in the last column.
data=[-3.997 4.402 0.000 703.050 -219.900 289.600 2.000 5.700 -49.100 11.100 3;...
-2.476 2.685 0.000 667.800 -220.210 290.000 1.955 5.710 -48.828 11.116 3; ...
-4.658 0.286 0.000 626.370 -220.420 290.380 2.019 5.991 -49.015 11.1210 2];
multcol = 11;
%unwrap the data
in=1;
for i=1:size(data,1)
data_uw(in:in+data(i,multcol)-1,:) = ...
repmat(data(i,1:multcol-1),[data(i,multcol) 1]);
in=in+data(i,multcol);
end
This works, but is relatively slow. The end result data_uw is each row of the input matrix, data, being replicated the number of times in the multiplicity column.
>> data_uw
data_uw =
Columns 1 through 7
-3.9970 4.4020 0 703.0500 -219.9000 289.6000 2.0000
-3.9970 4.4020 0 703.0500 -219.9000 289.6000 2.0000
-3.9970 4.4020 0 703.0500 -219.9000 289.6000 2.0000
-2.4760 2.6850 0 667.8000 -220.2100 290.0000 1.9550
-2.4760 2.6850 0 667.8000 -220.2100 290.0000 1.9550
-2.4760 2.6850 0 667.8000 -220.2100 290.0000 1.9550
-4.6580 0.2860 0 626.3700 -220.4200 290.3800 2.0190
-4.6580 0.2860 0 626.3700 -220.4200 290.3800 2.0190
Columns 8 through 10
5.7000 -49.1000 11.1000
5.7000 -49.1000 11.1000
5.7000 -49.1000 11.1000
5.7100 -48.8280 11.1160
5.7100 -48.8280 11.1160
5.7100 -48.8280 11.1160
5.9910 -49.0150 11.1210
5.9910 -49.0150 11.1210
Is there a better way to do this? Maybe there's a way to adapt the answer in the link above, but I'm not getting it.
Update with Answer
I've used the utility rude available at http://www.mathworks.co.uk/matlabcentral/fileexchange/6436-rude-a-pedestrian-run-length-decoder-encoder.
mult = data(:,multcol);
data = data(:,1:multcol-1);
iterations = sum(mult);
%preallocate the unwrapped data vector for speed
data_uw = zeros(iterations,multcol-1);
nstep = size(data,1);
ind = 1:nstep;
ind_uw = zeros(iterations,1);
ind_uw = rude(mult,ind);
data_uw = data(ind_uw,:);
This seems much faster. Rude makes use of the cumsum technique mentioned in another answer, so that will also work.