2

Referring to Reshape row wise w/ different starting/ending elements number @Divakar came with a nice solution but, what if the number of columns is not always the same?

Sample run -

>> A'
ans =
     4     9     8     9     6     1     8     9     7     7     7     4     6     2     7     1
>> out
out =
     4     9     8     9     0     0
     6     1     8     9     7     7
     7     4     6     2     7     1

I took only the first 4 terms of A and put them in out, then fill the rest 2 empty cell with 0's. So the ncols = [4 6 6]. Unfortunately vet2mat doesn't allow vector as columns number.

Any suggestions?

Community
  • 1
  • 1
gmeroni
  • 571
  • 4
  • 16
  • So, `sum(ncols)` has to be equal to `numel(A)`? `ncols` thus given would always satisfy that condition? – Divakar Jan 19 '15 at 14:30
  • [Related question](http://stackoverflow.com/q/27946552/2338750). – Stewie Griffin Jan 19 '15 at 14:33
  • @Divakar the expected output is `out`. If you look it closely is different from you question since there are 2 0's in the first row instead of the last one :). Yes, `numel(A) = sum(ncols)` – gmeroni Jan 19 '15 at 14:37
  • 1
    @StewieGriffin Hey, I _knew_ I had used `accumarray` this way before somewhere! :-) – Luis Mendo Jan 19 '15 at 16:30

2 Answers2

5

You can employ bsxfun's masking capability here -

%// Random inputs
A = randi(9,1,15)
ncols = [4 6 5]

%// Initialize output arary of transposed size as compared to the desired 
%// output arary size, as we need to insert values into it row-wise and MATLAB 
%// follows column-major indexing
out = zeros(max(ncols),numel(ncols)); 

mask =  bsxfun(@le,[1:max(ncols)]',ncols); %//'# valid positions mask for output
out(mask) = A; %// insert input array elements
out = out.' %//'# transpose output back to the desired output array size

Code run -

A =
     5     3     7     2     7     2     4     6     8     1     9     7     5     4     5
ncols =
     4     6     5
out =
     5     3     7     2     0     0
     7     2     4     6     8     1
     9     7     5     4     5     0
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • why use `double`? It seems like a waste. – Memming Jan 19 '15 at 14:42
  • @Memming Because `bsxfun` creates a logical array and as such you cant input/replace values from A into it. Alternative would be to create another array of zeros and then use the mask obtained from `bsxfun` for logical indexing. – Divakar Jan 19 '15 at 14:42
  • Thanks @Divakar but in this example you are taking row-wise and not column-wise. The first row should be `2 4 9 8 0 0 ` – gmeroni Jan 19 '15 at 14:48
  • Way to go! I was only left with the `accumarray` option :-) – Luis Mendo Jan 19 '15 at 16:14
1

You could use accumarray for that:

A = [4 9 8 9 6 1 8 9 7 7 7 4 6 2 7 1].'; %'// data
ncols = [4 6 6]; %// columns
n = max(ncols);
cs = cumsum(ncols);
ind = 1;
ind(cs+1) = 1;
ind = cumsum(ind(1:end-1)); %// `ind` tells the row for each element of A
result = accumarray(ind(:), A(:), [], @(x) {[x; zeros(n-numel(x),1)]}); %// split `A` as 
    %// dictated by `ind`, and fill with zeros. Each group is put into a cell.
result = [result{:}].'; %'// concatenate all cells
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147