1
votes

I have a vector A in Matlab of dimension (mxn)x1 composed by real numbers greater or equal then zero, e.g. m=3,n=4 A=[1;0;0;0;0.4;0.7;0.5;0.6;0.8;0;1;6] which looks like

           A=[1
              0 
              0 
              ---
              0 
              0.4 
              0.7 
              ---
              0.5 
              0.6 
              0.8
              ---
              0 
              1 
              6]

We can see that A is composed by n subvectors of dimension m. I have a vector B of dimension gx1, with g greater or equal than m, composed by ones and zeros such that the total number of ones is equal to m, e.g. g=9 B=[1;0;0;0;0;0;0;1;1] which looks like

B=[1 
   0 
   0 
   0 
   0 
   0 
   0 
   1 
   1]

I want to create a matrix C of dimension gxn in which the entries of each subvector of A are placed in correspondence of the ones in g for each column of B, e.g.

C=[1 | 0  |  0.5 | 0
   0 | 0  |  0   | 0
   0 | 0  |  0   | 0
   0 | 0  |  0   | 0
   0 | 0  |  0   | 0
   0 | 0  |  0   | 0
   0 | 0  |  0   | 0
   0 | 0.4|  0.6 | 1
   0 | 0.7|  0.8 | 6]

Loops are fine only if very fast. Real dimensions of matrices are very large (e.g. mxn=100000, g=50000)

2
Could you provide the example matrices in valid syntax? For A I'm not sure what it is supposed to be. - Daniel

2 Answers

2
votes

Approach #1 (bsxfun based linear indexing)

C = zeros(g,n)                         %// Pre-allocate
idx = bsxfun(@plus,find(B),[0:n-1]*g)  %// Indices where A elements are to be put
C(idx)= A                              %// Put A elements

Approach #2 (Direct replacement)

C = zeros(g,n) 
C(find(B),:) = reshape(A,m,[])

Pre-allocation: For faster pre-allocation you can do this instead in both of the above mentioned approaches -

C(g,n) = 0;
1
votes

You can also try the repmat and logical indexing approach. First, reshape your data so that it's in the right matrix form, so in your case 3 x 4, then use B as a logical mask and replicate it for as many times as we have columns in your matrix, then do an assignment. You would have to allocate a matrix that is the size of your desired output before doing this assignment. Something like this:

%// Your example data
m = 3; n = 4;
A = [1;0;0;0;0.4;0.7;0.5;0.6;0.8;0;1;6];
B = logical([1 0 0 0 0 0 0 1 1]).';

%// Relevant code
Am = reshape(A, m, n);
Bm = repmat(B, 1, n);
C = zeros(numel(B), 4);
C(Bm) = Am;

C is the desired result, where we get:

C =

    1.0000         0    0.5000         0
         0         0         0         0
         0         0         0         0
         0         0         0         0
         0         0         0         0
         0         0         0         0
         0         0         0         0
         0    0.4000    0.6000    1.0000
         0    0.7000    0.8000    6.0000

My gut feeling is that this will be slower than the bsxfun approach, but the above is more readable if you're not familiar with how bsxfun works.