Matlab, generate new matrix - matlab

How do you translate matrix of A [(N) x (N)] to matrix B [(2N) x (2N)], such that:
if A(i,j)>=0, then:
B(i,j) = [ A(i,j) 0
0 A(i,j)]
if A(i,j)<0, then:
B(i,j) = [ 0 A(i,j)
A(i,j) 0 ]
?
For example1 by:
1 2
3 4
I'm want to get:
1 0 2 0
0 1 0 2
3 0 4 0
0 3 0 4
For example2 by:
1 -2
3 -4
I'm want to get:
1 0 0 2
0 1 2 0
3 0 0 4
0 3 4 0

Use the Kronecker tensor product:
B = kron(A.*(A>=0), [1 0; 0 1]) + kron(A.*(A<0), [0 1; 1 0]);
Or maybe
B = kron(A.*(A>=0), [1 0; 0 1]) - kron(A.*(A<0), [0 1; 1 0]);
if you want all positive values (your examples and your original formulation don't agree on this)

very simple using logical conditions:
B=[A.*(A>=0), A.*(A<0) ; A.*(A<0), A.*(A>=0)];
for example,
A=[1 2 ; -3 4];
B =
1 2 0 0
0 4 -3 0
0 0 1 2
-3 0 0 4
Postscipt:
This answer was written to answer the question above in its initial forms:
How do you translate matrix of A [(N) x (N)] to matrix B [(2N) x (2N)], such that:
if A(i,j)>=0, then:
B(i,j) = [ A(i,j) 0
0 A(i,j)]
if A(i,j)<0, then:
B(i,j) = [ 0 A(i,j)
A(i,j) 0 ]
?
later the OP wrote down some examples that made clear what he\she were after.

Related

Perform "outer product" of 2-D matrix and return a 3-D array in MATLAB

I would like to do an operation on a 2-D matrix which somehow looks like the outer product of a vector. I already have written some codes for this task, but it is pretty slow, so I would like to know if there is anything I can do to accelerate it.
I would like to show the code I wrote first, followed by an example to illustrate the task I wanted to do.
My code, version row-by-row
function B = outer2D(A)
B = zeros(size(A,1),size(A,2),size(A,2)); %Pre-allocate the output array
for J = 1 : size(A,1)
B(J,:,:) = transpose(A(J,:))*A(J,:); %Perform outer product on each row of A and assign to the J-th layer of B
end
end
Using the matrix A = randn(30000,20) as the input for testing, it spends 0.317 sec.
My code, version page-by-page
function B = outer2D(A)
B = zeros(size(A,1),size(A,2),size(A,2)); %Pre-allocate the output array
for J = 1 : size(A,2)
B(:,:,J) = repmat(A(:,J),1,size(A,2)).*A; %Evaluate B page-by-page
end
end
Using the matrix A = randn(30000,20) as the input for testing, it spends 0.146 sec.
Example 1
A = [3 0; 1 1; 1 0; -1 1; 0 -2]; %A is the input matrix.
B = outer2D(A);
disp(B)
Then I would expect
(:,:,1) =
9 0
1 1
1 0
1 -1
0 0
(:,:,2) =
0 0
1 1
0 0
-1 1
0 4
The first row of B, [9 0; 0 0], is the outer product of [3 0],
i.e. [3; 0]*[3 0] = [9 0; 0 0].
The second row of B, [1 1; 1 1], is the outer product of [1 1],
i.e. [1; 1]*[1 1] = [1 1; 1 1].
The third row of B, [1 0; 0 0], is the outer product of [1 0],
i.e. [1; 0]*[1 0] = [1 0; 0 0].
And the same for the remaining rows.
Example 2
A =
0 -1 -2
0 1 0
-3 0 2
0 0 0
1 0 0
B = outer2D(A)
disp(B)
Then, similar to the example 1, the expected output is
(:,:,1) =
0 0 0
0 0 0
9 0 -6
0 0 0
1 0 0
(:,:,2) =
0 1 2
0 1 0
0 0 0
0 0 0
0 0 0
(:,:,3) =
0 2 4
0 0 0
-6 0 4
0 0 0
0 0 0
Because the real input in my project is like in the size of 30000 × 2000 and this task is to be performed for many times. So the acceleration of this task is quite essential for me.
I am thinking of eliminating the for-loop in the function. May I have some opinions on this problem?
With auto expansion:
function B = outer2D(A)
B=permute(permute(A,[3 1 2]).*A',[2 3 1]);
end
Without auto expansion:
function B = outer2Dold(A)
B=permute(bsxfun(#times,permute(A,[3 1 2]),A'),[2 3 1]);
end
Outer products are not possible in the matlab language.

Generate matrix of vectors from labels for multiclass classification (vectorized)

I'm structuring my input for a multiclass classifier (m data points, k classes). In my input, I have the labels for the training data as integers in a vector y (i.e. y is m dimensional and each entry in y is an integer between 1 and k).
I'd like to transform this into an m x k matrix. Each row has 1 at the index corresponding to the label of that data point and 0 otherwise (e.g. if the data point has label 3, the row looks like [0 0 1 0 0 0 0 ...]).
I can do this by constructing a vector a = [1 2 3 4 ... k] and then computing
M_ = y*(1./b)
M = M_ .== 1
(where ./ is elementwise division and .== is elementwise logical equals). This achieves what I want by setting everything in the intermediate matrix that is not exactly 1 to 0.
But this solution seems silly and roundabout. Is there a more direct way that I'm missing?
You can use logical arrays:
M = [1:k] == y;
Given a label vector y such as [1 2 2 1 3 2 3 1] and a number of classes k such as 3, you can convert this to a label matrix Y as follows.
function Y = labelmatrix(y, k)
m = length(y);
Y = repmat(y(:),1,k) .== repmat(1:k,m,1);
The idea is to perform the following expansions:
1 1 1 1 2 3
2 2 2 1 2 3
2 2 2 1 2 3
1 1 1 .== 1 2 3
3 3 3 1 2 3
2 2 2 1 2 3
3 3 3 1 2 3
1 1 1 1 2 3
This yields:
1 0 0
0 1 0
0 1 0
1 0 0
0 0 1
0 1 0
0 0 1
1 0 0
Or just by indexing:
%// Dummy code to generate some input data
y = [1 4 3 7 2 1];
m = length(y);
k = max(y);
%// Actual conversion using y elements as index
M = zeros(m, k);
M(sub2ind(size(M), [1:m], y)) = 1
%// Result
M =
1 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 1
0 1 0 0 0 0 0
1 0 0 0 0 0 0

Generate derived matrix from index vector in matlab

Consider an index vector consisting of ones and zeros:
I=[0 0 1 0 1 1 0 0 0];
How can I easily generate the following matrix in matlab:
J=[0 2;
1 1;
0 1;
1 2;
0 3];
Use diff:
I = [0 0 1 0 1 1 0 0 0];
d = diff(I);
ind = [1 find(d~=0)+1]; %// starting index of each new value
rep = diff([ind numel(I)+1]); %// number of repetitions of each new value
J = [ I(ind).' rep.' ];
Using strfind for a slightly bigger example -
I =[1 1 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0]
zero_pos = ['0' num2str(bsxfun(#eq,I,0),'%1d') '0']
ind3 = [ strfind(zero_pos,'01') ; strfind(zero_pos,'10')]
counts = diff(ind3(:))
var = zeros(numel(counts),1);
var(2:2:end)=1;
J = [var counts];
if ind3(1,1)-1>0
J = [1 ind3(1,1)-1;J];
end
Output
J =
1 2
0 2
1 1
0 1
1 2
0 3
1 4
0 2

Compare two vectors of unequal lengths to get a logical array

I need to vectorize the following code:
a = [1 2 3 2 3 1];
b = [1 2 3];
for i = 1:length(a)
for j = 1:length(b)
r(i, j) = (a(i) == b(j));
end
end
The output r should be a logical array:
1 0 0
0 1 0
0 0 1
0 1 0
0 0 1
1 0 0
The closest I can get is:
for j = 1:length(b)
r(:, j) = (a == b(j));
end
Iterating through the shorter vector is obviously more efficient as it generates fewer for iterations. The correct solution should have no for-loops whatsoever.
Is this possible in MATLAB/Octave?
Here's a simple solution using bsxfun.
bsxfun(#eq,b,a')
ans =
1 0 0
0 1 0
0 0 1
0 1 0
0 0 1
1 0 0
bsxfun(#eq, a', b)

Is there any function in MATLAB for changing the form of a matrix?

I have to get the unknown matrix by changing the form of a known matrix considering the following rules:
H = [-P'|I] %'
G = [I|P]
where
H is a known matrix
G is an unknown matrix which has to be calculated
I is the identity matrix
So for example, if we had a matrix,
H = [1 1 1 1 0 0;
0 0 1 1 0 1;
1 0 0 1 1 0]
its form has to be changed to
H = [1 1 1 1 0 0;
0 1 1 0 1 0;
1 1 0 0 0 1]
So
-P' = [1 1 1;
0 1 0;
1 1 0]
and in case of binary matrices -P = P.
Therefore
G = [1 0 0 1 1 1;
0 1 0 0 1 0;
0 0 1 1 1 0]
I know how to solve it on paper by performing basic row operations but haven't figured out how to solve it using MATLAB yet.
What is the method for solving the given problem?
If the order of columns in -P' doesn't matter, here's one solution using the function ISMEMBER:
>> H = [1 1 1 1 0 0; 0 0 1 1 0 1; 1 0 0 1 1 0]; %# From above
>> pColumns = ~ismember(H',eye(3),'rows') %'# Find indices of columns that
%# are not equal to rows
pColumns = %# of the identity matrix
1
0
1
1
0
0
>> P = -H(:,pColumns)' %'# Find P
P =
-1 0 -1
-1 -1 0
-1 -1 -1
>> G = logical([eye(3) P]) %# Create the binary matrix G
G =
1 0 0 1 0 1
0 1 0 1 1 0
0 0 1 1 1 1
NOTE: This solution will work properly for integer or binary values in H. If H has floating-point values, you will likely run into an issue with floating-point comparisons when using ISMEMBER (see here and here for more discussion of this issue).