Inserting columns to a matrix in Matlab - matlab

I'd like to insert columns to a matrix, but the insertion column positions within the matrix differ by row. How can I do this without using for-loop?
Following is a simplified example in MATLAB;
From A,X,P, I want to get APX without using for-loop.
>> A = zeros(4,5) % inclusive matrix
A =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>> X = [9,8;5,7;8,3;6,7] % data to insert
X =
9 8
5 7
8 3
6 7
>> P = [3;2;4;1] % insertion position within the matrix
P =
3
2
4
1
>> APX = [0,0,9,8,0;0,5,7,0,0;0,0,0,8,3;6,7,0,0,0] % what I want
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0

It's simply determining the right column-major indices to access the matrix so you can populate it with your desired values. This first requires generating the right row and column values to access the right positions in APX so you can use X to populate those positions.
Using P, each element tells you which column you should start populating for each row of X. You will need to generate column indices in increasing order up to as many columns as there are in X. To generate the row indices, simply create a matrix that is the same size as X where each column spans from 0 up to as many rows as there are in X minus 1 (i.e. 0:size(X,2)-1). This matrix gives you the correct offsets so that you can take P and add it with this matrix. Once you do that you will have a column index matrix that tells you specifically where each element should go with regards to the columns of the output matrix per row of P. Finally, use sub2ind to generate the column-major indices using the rows and columns generated above to place X in APX.
In other words:
P = [3;2;4;1];
X = [9,8;5,7;8,3;6,7];
rowInd = repmat((1:size(X,1)).', 1, size(X,2)); %'
colInd = bsxfun(#plus, P, 0:size(X,2)-1);
APX = zeros(size(X,1), max(colInd(:)));
APX(sub2ind(size(APX), rowInd, colInd)) = X;
To generate the row locations, we use repmat to create a matrix that is the same size as X where each column spans from 1 up to as many rows as X. To generate the column locations, we use bsxfun to create a matrix where each column is the vector P but increasing by 1 per column. We then create APX to be of compatible size then use sub2ind to finally populate the matrix.
With your above test inputs, we get:
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
Minor Note
You really should actually try using loops before trying it vectorized. Though using loops was slow in previous versions of MATLAB, MATLAB R2015b has an improved JIT engine where loops are now competitive. You should time your code using loops and ensuring that it is justifiable before switching to vectorized implementations.

Related

Matlab: enter same vector repeatedly to matrix using logical indexing

I would like to enter the same vector of numbers repeatedly to an existing matrix at specific (row) logical indices. This is like an extension of entering just a single number at all logical index positions (at least in my head).
I.e., it is possible to have
mat = zeros(5,3);
rowInd = logical([0 1 0 0 1]); %normally obtained from previous operation
mat(rowInd,1) = 15;
mat =
0 0 0
15 0 0
0 0 0
0 0 0
15 0 0
But I would like to do sth like this
mat(rowInd,:) = [15 6 3]; %rows 2 and 5 should be filled with these numbers
and get an assignment mismatch error.
I want to avoid for loops for the rows or assigning vector elements single file. I have the strong feeling there is an elementary matlab operation that should be able to do this? Thanks!
The problem is that your indexing picks two rows from the matrix and tries to assign a single row to them. You have to replicate the targeted row to fit your indexing:
mat = zeros(5,3);
rowInd = logical([0 1 0 0 1]);
mat(rowInd,:) = repmat([15 6 3],sum(rowInd),1)
This returns:
mat =
0 0 0
15 6 3
0 0 0
0 0 0
15 6 3

How to efficiently select only certain columns of a triangular matrix

I have the following problem:
I need certain columns of a huge triangular 1-0 matrix.
E.g.
Matrix =
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
Index =
[1 4]
Result =
1 0
1 0
1 0
1 1
I figured the easiest way would be:
index = [10 20 300] %arbitrary index
buf = tril(ones(60000,60000))
matr = buf(:,index)
However, this does not work as the buffer matrix is too large and leads to MATLAB throwing an error. Thus, this approach is blocked.
How can I solve that problem efficiently? (E.g. it would be trivial by just looping over the index array and concatenating self-made rows, however this would be slow and I was hoping for a faster approach)
The index array will not be larger than 1/10th of the available columns.
If the matrix contains ones on the main diagonal and below, and zeros otherwise, you can do it as follows without actually generating the matrix:
N = 10; % number of rows of (implicit) matrix
Index = [1 4]; % column indices
Result = bsxfun(#ge, (1:N).', Index);

finding indices of multiple corresponding rows of a matrix in matlab [duplicate]

This question already has answers here:
How can I find indices of each row of a matrix which has a duplicate in matlab?
(3 answers)
Closed 8 years ago.
I have two matrices and I want to find the indices of rows in Matrix B which have the same row values in Matrix A. Let me give a simple example:
A=[1,2,3; 2,3,4; 3,5,7; 1,2,3; 1,2,3; 5,8,6];
B=[1,2,3; 29,3,4; 3,59,7; 1,29,3; 1,2,3; 5,8,6;1,2,3];
For example, for first row in matrix A, The row1, row5, and row7 in Matrix B are correspondences.
I have written below code but it doesn't return back all indices which have the same row value in matrix A and only one of them (row7) is backed !!
A_sorted = sort(A,2,'descend'); % sorting angles
B_sorted = sort(B,2,'descend'); % sorting angles
[~,indx]=ismember(A_sorted,B_sorted,'rows')
the result is
indx_2 =
7
0
0
7
7
6
It means for the first row in matrix A , only one row ( row 7) in Matrix B is available !! But as you can see for first row in matrix A there is three correspondent rows in matrix B (Row 1, row 5 and row 7)
I think the best strategy is to apply ismember to unique rows
%make matrix unique
[B_unique,B2,B3]=unique(B_sorted,'rows')
[~,indx]=ismember(A_sorted,B_unique,'rows')
%For each row in B_unique, get the corresponding indices in B_sorted
indx2=arrayfun(#(x)find(B3==x),indx,'uni',0)
If you want to compare all pairs of rows between A and B, use
E = squeeze(all(bsxfun(#eq, A, permute(B, [3 2 1])), 2));
or equivalently
E = pdist2(A,B)==0;
In your example, this gives
E =
1 0 0 0 1 0 1
0 0 0 0 0 0 0
0 0 0 0 0 0 0
1 0 0 0 1 0 1
1 0 0 0 1 0 1
0 0 0 0 0 1 0
The value E(ia,ib) tells you if the ia-th row of A equals the ib-th row of B.

Resorting rows in matrix in non-decreasing order based on the entries of an arbitrary column

I am working with nx2 matrices in Matlab, and what I'm trying to do is fairly simple in principle. I randomly generate a square matrix, I run it through a series of functions and I get an mx2 matrix. I use the unique function on the rows to get rid of repeated rows and I end up with an nx2 matrix. What I'm having trouble doing is further reducing this matrix so that for all entries in the first column that have the exact same entry, only keep the row with the highest number on the second column.
I was using a loop to check the ith and (i+1)th entries of the first column and store the rows with the highest value in the second column, but I am trying to avoid for-loops as much as possible.
If anyone has an idea or suggestion please let me know!
Example:
0 0 0 0
0 1 0 1 0 3
A= 0 3 ---> unique(A, 'rows') = 0 3 --WANT--> 1 1
1 0 1 0 2 4
1 0 1 1
0 0 2 1
2 1 2 4
1 1
2 4
What you are looking for is:
[u,~,n] = unique(A(:,1));
B = [u, accumarray(n, A(:,2), [], #max)];
I don't exactly understand your problem description, but it sounds like sortrows() may be of some help to you.

shift of rows among matrices matlab

I am doing a project on Particle Swarm optimization, coding in Matlab. I need to replace the rows of matrix A by some of the rows from matrix B and remove those rows from matrix B as well. How can I do that?
Put you row indices in vectors, say
indexA=[0 0 0 1 0 1 1 0].
indexB=[0 1 0 1 0 1].
Partition B into
A(indexA,:) = B(indexB,:);
B(indexB,:) = [];