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;
Related
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{:});
I have a logical vector in which I would like to iterate over every n-elements. If in any given window at least 50% are 1's, then I change every element to 1, else I keep as is and move to the next window. For example.
n = 4;
input = [0 0 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 0 0 1];
output = func(input,4);
output = [0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1];
This function is trivial to implement but is it possible to apply a vectorized implementation using logical indexing?. I am trying to build up the intuition of applying this technique.
here's a one liner (that works for your input):
func = #(input,n) input | kron(sum(reshape(input ,n,[]))>=n/2,ones(1,n));
of course, there are cases to solve that this doesnt answer, what if the size of the input is not commensurate in n? etc...
i'm not sure if that's what you meant by vectorization, and I didnt benchmark it vs a for loop...
Here is one way of doing it. Once understood you can compact it in less lines but I'll details the intermediate steps for the sake of clarity.
%% The inputs
n = 4;
input = [0 0 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 0 0 1];
1) Split your input into blocks of size n (note that your final function will have to check that the number of elements in input is a integer multiple of n)
c = reshape(input,n,[]) ;
Gives you a matrix with your blocks organized in columns:
c =
0 0 0 0 0
0 1 0 1 0
0 1 0 0 0
1 0 1 1 1
2) Perform your test condition on each of the block. For this we'll take advantage that Matlab is working column wise for the sum function:
>> cr = sum(c) >= (n/2)
cr =
0 1 0 1 0
Now you have a logical vector cr containing as many elements as initial blocks. Each value is the result of the test condition over the block. The 0 blocks will be left unchanged, the 1 blocks will be forced to value 1.
3) Force 1 columns/block to value 1:
>> c(:,cr) = 1
c =
0 1 0 1 0
0 1 0 1 0
0 1 0 1 0
1 1 1 1 1
4) Now all is left is to unfold your matrix. You can do it several ways:
res = c(:) ; %% will give you a column vector
OR
>> res = reshape(c,1,[]) %% will give you a line vector
res =
0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1
I create a matrix b from a matrix a in the following way:
a=[1 2 ; 3 4];
b= [a zeros(2); zeros(2) a]
b =
1 2 0 0
3 4 0 0
0 0 1 2
0 0 3 4
Successively, I want to insert a line and a column of zeros at a certain point of the matrix. Let's say at middle way:
idx=2;
c=[b(1:idx,:); zeros(1,4); b(idx+1:end,:)]
c =
1 2 0 0
3 4 0 0
0 0 0 0
0 0 1 2
0 0 3 4
c=[c(:,1:idx) zeros(5,1) c(:,idx+1:end)]
c =
1 2 0 0 0
3 4 0 0 0
0 0 0 0 0
0 0 0 1 2
0 0 0 3 4
Is there a more intelligent way of doing this?
Here is another way(I don't know if it is a more intelligent way).
Assuming that you have the row index as row and the column index as col:
sc = size(b) + 1;
c = zeros(sc);
ROW = true(sc(1), 1);
ROW(row) = false;
COL = true(1, sc(2));
COL(col) = false;
Then in MATLAB r2016b /Octave you can write
c(ROW & COL)=b;
In pre 2016b you can use bsxfun
c(bsxfun(#and, ROW , COL))=b;
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.
For neural networking, I would like to represent a column vector y = [1;2;3] in a matrix like so:
y = [1 0 0;
0 1 0;
0 0 1]
My vector y is very large, and so hardcoding is not an option. Also, I would like to avoid using for-loops.
What I did so far:
y1 =[y; zeros(1,length(y)) ;zeros(1,length(y))] % add two rows with zeros in orde to give y the right format
idx = find(y1(1,:) == 2); % find all the columns containing a 2
y1(:,idx(1):idx(end)) = y1(:,[0;1;0]); % this does not work because now I am comparing a matrix with a vector
I also tried this:
y1( y1 == [2;0;0] )=[0;1;0]; % This of course does not work
Is there a way to specify I want to compare columns in y1 == [2;0;0], or is there another way to solve this?
From the context of your question, you wish to find a matrix where each column is an identity vector. For an identity vector, each column in this matrix is a non-zero vector where 1 is set in the position of the vector denoted by each position of y and 0 otherwise. Therefore, let's say we had the following example:
y = [1 5 4 3]
You would have y_out as the final matrix, which is:
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
There are several ways to do this. The easiest one would be to declare the identity matrix with eye, then let y pick out those columns that you want from this matrix and place them as columns into your final matrix. If y had all unique values, then we would simply be rearranging the columns of this identity matrix based on y. As such:
y_out = eye(max(y));
y_out = y_out(:,y)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
Another way would be to declare a sparse matrix, where each row index is simply those elements from y and each column index is increasing from 1 up to as many elements as we have y:
y_out = sparse(y, 1:numel(y), 1, max(y), numel(y));
y_out = full(y_out)
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
One more way would be to use sub2ind to find linear indices into your matrix, then access those elements and set them to 1. Therefore:
ind = sub2ind([max(y) numel(y)], y, 1:numel(y));
y_out = zeros(max(y), numel(y));
y_out(ind) = 1
y_out =
1 0 0 0
0 0 0 0
0 0 0 1
0 0 1 0
0 1 0 0
This works even if y has "missing" values:
n = numel(y);
y_matrix = zeros(n, max(y));
y_matrix((1:n) + (y-1)*n) = 1;
Example:
y = [1 5 3 2];
gives
y_matrix =
1 0 0 0 0
0 0 0 0 1
0 0 1 0 0
0 1 0 0 0
You can use bsxfun:
y_out = bsxfun(#eq, (1:max(y)).', y);
Not as efficient as the #rayryeng's answer but this might also help,
Also if there are repeated values in y this code works fine.
a = [1 2 3 2 5 7 6 8];
[X,Y] = meshgrid(a,1 : length(a));
A = X == Y;
A =
1 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1