From: Matthias Fripp on
I have several row vectors that I would like repeated various numbers of times vertically, to produce a large matrix. For example, vector 1 should be repeated 2 times, vector 2 should be repeated 5 times, vector 3 should be repeated 3 times, etc. This will create a matrix divided vertically into several "blocks", each of which consist of some number of repetitions of one of the original vectors.

I have matlab code to do this with a for loop (below). But is there any way to do this directly with vector/matrix operations? I haven't mastered all of Matlab's indexing options yet!

==== example code starts here =====

lines=[2 5; 4 2; 6 7];
starts=[1 3 8 11];

% Is there a vectorized way to repeat the rows from "lines"
% in vertical blocks, starting at the rows listed in "starts"
% (neglecting the last)?
expanded=zeros(starts(end)-1, size(lines, 2));
for i=1:length(starts)-1,
expanded(starts(i):starts(i+1)-1,:)=repmat(lines(i, :), starts(i+1)-starts(i), 1);
end
From: Sean on
"Matthias Fripp" <mfripp.mini.turing.test(a)gmail.com> wrote in message
> ==== example code starts here =====
>
> lines=[2 5; 4 2; 6 7];
> starts=[1 3 8 11];
>
> % Is there a vectorized way to repeat the rows from "lines"
> % in vertical blocks, starting at the rows listed in "starts"
> % (neglecting the last)?
> expanded=zeros(starts(end)-1, size(lines, 2));
> for i=1:length(starts)-1,
> expanded(starts(i):starts(i+1)-1,:)=repmat(lines(i, :), starts(i+1)-starts(i), 1);
> end

Not sure if it'll be any faster but here's one way:

lines=[2 5; 4 2; 6 7];
starts=[1 3 8 11];

Term = [diff(starts)]';
Expan = cell2mat(cellfun(@(x,y)(repmat(x,y,1)),mat2cell(lines,ones(size(lines,1),1)),mat2cell(Term,ones(numel(Term),1)),'UniformOutput',false));
From: Jan Simon on
Dear Matthias,

> lines=[2 5; 4 2; 6 7];
> starts=[1 3 8 11];
>
> % Is there a vectorized way to repeat the rows from "lines"
> % in vertical blocks, starting at the rows listed in "starts"
> % (neglecting the last)?
> expanded=zeros(starts(end)-1, size(lines, 2));
> for i=1:length(starts)-1,
> expanded(starts(i):starts(i+1)-1,:)=repmat(lines(i, :), starts(i+1)-starts(i), 1);
> end

Sorry if this appears twice - my browser boke the posting process with a "cannot find server" message. ???

The idea is to create the list of indices instead of the matrix directly:
lines = [2 5; 4 2; 6 7];
s = [1 3 8 11];
v(s) = 1;
v = cumsum(v);
expanded = lines(v(1:end - 1), :)

Good luck, Jan
From: Matthias Fripp on
Dear Jan,

Thanks very much -- that's a really neat solution, and just what I was looking for!

Matthias

"Jan Simon" <matlab.THIS_YEAR(a)nMINUSsimon.de> wrote in message <i0l48d$8fl$1(a)fred.mathworks.com>...
> The idea is to create the list of indices instead of the matrix directly:
> lines = [2 5; 4 2; 6 7];
> s = [1 3 8 11];
> v(s) = 1;
> v = cumsum(v);
> expanded = lines(v(1:end - 1), :)
 | 
Pages: 1
Prev: array assignment issue
Next: find 'first' option