Using a Matrix to Populate Every Other Value in a Column - matlab

Im learning matlab as I have free time.
Matrix B is half the length of Matrix C
I want Every Value in the first column of matrix B to populate every other Value in the first column of Matrix C
To do this Im using a for loop. Currently I get every other value populated with the last number in the column of matrix B. What do I need to change?
Z=length(A);
X = length(B);
C = zeros(size(A);
for n = 1:2:Z
for m = 1:1:X
C(n,1) = B(m,1);
end
end

You can use the kron function:
reps = 2;
delta = zeros(reps,1);
B = magic(5);
C = kron(B,delta);
Here rep indicates that every second value should be taken from B. But you can also duplicate the values by using delta = ones(reps,1);, or any mix that you are interested in, by modifying delta.
Additionally you can change the dimension of delta to a row vector and then can duplicate values along the rows. Or by allowing delta to be a matrix you can be get more fancy stuff.

You can simply write this:
B = magic(4); % The small matrix with the values
C = zeros(size(A)*2); % The matrix to fill the values in
C(1:2:end,1) = B(:,1) % populating the matrix
and you get:
C =
16 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Related

Matrix operator to stack the rows of a matrix on the "diagonal"

I am looking for a matrix operator (or a mathematical expression) that does the following:
I have a matrix A of dimension 3 by 5:
a_11 a_12 a_13 a_14 a_15
a_21 a_22 a_23 a_24 a_25
a_31 a_32 a_33 a_34 a_35
I want to obtain the matrix 3 by 15:
a_11 a_12 a_13 a_14 a_15 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 a_21 a_22 a_23 a_24 a_25 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 a_31 a_32 a_33 a_34 a_35
I have tried to use Kronecker products but I didn't arrive to any solution.
You could solve it using the following:
a = [1,2,3;4,5,6;7,8,9]
sz = size(a) % find the dimensions
m = zeros(sz(1), prod(sz)) %Create a matrix of zeros
for row = 1:sz(1)
m(row,(1:sz(2)) + (row-1) * sz(2)) = a(row,:) %replace each row accordingly
end
m =
1 2 3 0 0 0 0 0 0
0 0 0 4 5 6 0 0 0
0 0 0 0 0 0 7 8 9
Not a matrix-algebra expression, but in case it helps: this can be easily done using num2cell to split the matrix into a cell array of its rows, and passing a comma-separated list of those rows to blkdiag:
A = randi(9,3,5); % example input
A_cell = num2cell(A, 2);
result = blkdiag(A_cell{:});

How to sort the columns of a matrix in order of some other vector in MATLAB?

Say I have a vector A of item IDs:
A=[50936
332680
107430
167940
185820
99732
198490
201250
27626
69375];
And I have a matrix B whose rows contains values of 8 parameters for each of the items in vector A:
B=[0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 1 0 1 1 1
1 0 1 0 0 1 0 1 1 1
0 0 1 0 0 0 0 1 0 1
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1];
So, column 1 in matrix B represents data of item in row 1 of vector A, column 2 in matrix B represents data of item in row 2 of vector A, and so on. However, I want matrix B to contain the information in a different order of items stored in vector A2:
A2=[185820
198490
69375
167940
99732
332680
27626
107430
50936
201250];
How do I sort them, so that column 1 of matrix B contains data for item in row 1 of vector A2, column 2 of matrix B contains data for item in row 2 of vector A2, and so on?
My extremely crude solution to do this is the following:
A=A'; A2=A2';
for i=1:size(A,2)
A(2:size(B,1)+1,i)=B(:,i);
end
A2(2:size(B,1)+1,:)=zeros(size(B,1),size(B,2));
for i=size(A2,2)
for j=size(A,2)
if A2(1,i)==A(1,j)
A2(2:end,i)=A(2:end,j);
end
end
end
B2 = A2(2:end,:);
But I would like to know a cleaner, more elegant and less time consuming method to do this.
A possible solution
You can use second output of ismember function.
[~ ,idx] = ismember(A2,A);
B2 = B(:,idx);
Update:I tested both my solution and another proposed by hbaderts
disp('-----ISMEMBER:-------')
tic
[~,idx]=ismember(A2,A);
toc
disp('-----SORT:-----------')
tic
[~,idx1] = sort(A);
[~,idx2] = sort(A2);
map = zeros(1,size(idx2));
map(idx2) = idx1;
toc
Here is the result in Octave:
-----ISMEMBER:-------
Elapsed time is 0.00157714 seconds.
-----SORT:-----------
Elapsed time is 4.41074e-05 seconds.
Conclusion: the sort method is more efficient!
As both A and A2 contain the exact same elements, just sorted differently, we can create a mapping from the A-sorting to the A2-sorting. For that, we run the sort function on both and save indexes (which are the second output).
[~,idx1] = sort(A);
[~,idx2] = sort(A2);
Now, the first element in idx1 corresponds to the first element in idx2, so A(idx1(1)) is the same as A2(idx2(1)) (which is 27626). To create a mapping idx1 -> idx2, we use matrix indexing as follows
map = zeros(size(idx2));
map(idx2) = idx1;
To sort B accordingly, all we need to do is
B2 = B(:, map);
[A2, sort_order] = sort(A);
B2 = B(:, sort_order)
MATLAB's sort function returns the order in which the items in A are sorted. You can use this to order the columns in B.
Transpose B so you can concatenate it with A:
C = [A B']
Now you have
C = [ 50936 0 0 1 1 0 0 0 0;
332680 0 0 0 0 0 0 0 0;
107430 0 0 1 1 1 0 0 0;
167940 0 0 0 0 0 0 0 0;
185820 0 0 0 0 0 0 0 0;
99732 0 0 1 1 0 0 0 0;
198490 0 0 0 0 0 0 0 0;
201250 0 0 1 1 1 1 0 0;
27626 0 0 1 1 0 0 0 0;
69375 0 0 1 1 1 0 0 1];
You can now sort the rows of the matrix however you want. For example, to sort by ID in ascending order, use sortrows:
C = sortrows(C)
To just swap rows around, use a permutation of 1:length(A):
C = C(perm, :)
where perm could be something like [4 5 6 3 2 1 8 7 9 10].
This way, your information is all contained in one structure and the data is always correctly matched to the proper ID.

Insert an identity matrix into a larger dimension of null matrix

Suppose i have an identity matrix .
I=eye(3)
which will produce
I = [1 0 0
0 1 0
0 0 1]
Now i want to insert I into a (5X5) null matrix such that my result will be
N = [0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1]
How could i achieve this efficiently .Thanks in advace
With the Image processing toolbox, this could be done using padarray like this:
padarray(eye(3), [2 2], 'pre');
padarray pads an array with zeros. The [2 2] part says how many zeros to pad it with, in this case 2 rows and 2 columns. pre means you want it in front of the matrix, not after it (post).
Without it, you need to tweak it a bit more. One option could be to create an identity matrix of the full size, then make the first elements zero:
m = 5; %// size of matrix
n = 3; %// size of identity matrix
a = eye(m);
a(1:m-n,1:m-n) = 0;
a =
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
... or:
a = zeros(m);
a(m-n+1:m,m-n+1:m) = eye(n)
... or using sparse:
full(sparse(m-n+1:m,m-n+1:m,1))
Alternatively,
m = 5;
n = 3;
a = diag( [zeros(1, m-n), ones(1,n)] );

MATLAB swap columns of two different matrices

Im using matlab and am having some difficulty. I am trying to swap the columns of one matrix (A) with the column of another matrix (B). For Example:
A =
4 6 5
7 8 4
6 5 9
1 0 0
0 1 0
0 0 1
B =
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 -1 0 0
0 0 0 0 -1 0
0 0 0 0 0 -1
Is there a way to tell Matlab to switch, for instance, column 1 in A with column 3 in B?
You can actually perform this column swap in one line and without the need for dummy variables using the function DEAL:
[A(:,1),B(:,3)] = deal(B(:,3),A(:,1));
tmp = A(:,1);
A(:,1) = B(:,3);
B(:,3) = tmp;
Use
A(:,1) = B(:,3);
Or to actually swap them, you can use:
dummy = A(:,1);
A(:,1) = B(:,3);
B(:,3) = dummy;

Using find function on columns and rows in matlab

I am having some problems with the find function in MATLAB. I have a matrix consisting of zeros and ones (representing the geometry of a structural element), where material is present when the matrix element = 1, and where no material is present when the matrix element = 0. The matrix may have the general form shown below (it will update as the geometry is changed, but that isn't too important).
Geometry = [0 0 0 0 0 0 0 0 0 0;
0 0 1 0 1 0 1 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 1 0 0;
0 0 0 0 0 0 0 0 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 1 1 1 0 1 0 0;
0 0 0 0 0 0 0 0 0 0;]
I'm trying to find the the rows and columns that are not continuously connected (i.e. where the row and columns are not all equal to 1 between the outer extents of the row or column) and then update them so they are all connected. I.e. the matrix above becomes:
Geometry = [0 0 0 0 0 0 0 0 0 0;
0 0 1 1 1 1 1 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 1 1 1 1 1 0 0;
0 0 0 0 0 0 0 0 0 0;]
The problem I am having is I want to be able to find the indices of the first and last element that is equal to 1 in each row (and column), which will then be used to update the geoemtry matrix.
Ideally, I want to represent these in vectors, so going across the columns, find the row number of the first element equal to 1 and store this in a vector called rowfirst.
I.e.:
rowfirst = zeros(1,numcols)
for i = 1:numcols % Going across the columns
rowfirst(i) = find(Geometry(i,1) == 1, 1,'first')
% Store values in vector called rowfirst
end
and the repeat this for the columns and to find the last elements in each row.
For some reason, I can't get the values to store properly in the vector, does anyone have an idea of where I'm going wrong?
Thanks in advance. Please let me know if that isn't clear, as I may not have explained the problem very well.
0) bwmorph(Geometry,'close') dose it all in one line. If the holes may be bigger, try bwmorph(Geometry,'close',Inf).
Regarding your attempt:
1) It should be Geometry(i,:) instead of Geometry(i,1).
2) Your real problem here is empty matrices. Actually, what do you want rowfirst(i) to be if there are no 1s in the i'th row?
Ok, I can spot two mistakes:
You should use an array as the first argument of find. So, if you want to find the row number of the first element of each column, then you should use find(Geometry(:, i), 1, 'first').
Find returns an empty array if the column contains only zeros. You should handle this case and decide what number you want to put into rownumber (e.g. you can put -1, to indicate that the corresponding column contains no non-zero elements).
Following the above, you can try this:
for i = 1:numcols
tmp = find(Geometry(:, i), 1, 'first');
if(tmp)
rowfirst(i) = tmp;
else
rowfirst(i) = -1;
end;
end;
I'm pretty sure there's a more efficient way of doing this, but if you replace your call to find with this, it should work ok:
find(Geometry(i,:), 1,'first')
(otherwise you're just looking at the first cell of the ith row. And the == 1 is useless, since find already returns only non-zero elements, and your matrix is binary)
Use the AccumArray() function to find the min and max col (row) number.
Imagine finding the last (first) row in each column that contains a NaN.
a = [1 nan nan nan ;
2 2 3 4;
3 nan 3 3;
4 nan 4 4]
This code gets the row indices for the last NaN in each column.
[row,col] = find(isnan(a))
accumarray(col,row,[],#max)
This code gets the row indices for the first NaN in each column.
[row,col] = find(isnan(a))
accumarray(col,row,[],#min)
Swap the row and col variables to scan row-wise instead of column-wise.
This answer inspired by Finding value and index of min value in a matrix, grouped by column values