Expand a matrix with polynomials - matlab

Say I have a matrix A with 3 columns c1, c2 and c3.
1 2 9
3 0 7
3 1 4
And I want a new matrix of dimension (3x3n) in which the first column is c1, the second column is c1^2, the n column is c1^n, the n+1 column is c2, the n+2 column is c2^2 and so on. Is there a quickly way to do this in MATLAB?

Combining PERMUTE, BSXFUN, and RESHAPE, you can do this quite easily such that it works for any size of A. I have separated the instructions for clarity, you can combine them into one line if you want.
n = 2;
A = [1 2 9; 3 0 7; 3 1 4];
[r,c] = size(A);
%# reshape A into a r-by-1-by-c array
A = permute(A,[1 3 2]);
%# create a r-by-n-by-c array with the powers
A = bsxfun(#power,A,1:n);
%# reshape such that we get a r-by-n*c array
A = reshape(A,r,[])
A =
1 1 2 4 9 81
3 9 0 0 7 49
3 9 1 1 4 16

Try the following (don't have access to Matlab right now), it should work
A = [1 2 9; 3 0 7; 3 1 4];
B = [];
for i=1:n
B = [B A.^i];
end
B = [B(:,1:3:end) B(:,2:3:end) B(:,3:3:end)];
More memory efficient routine:
A = [1 2 9; 3 0 7; 3 1 4];
B = zeros(3,3*n);
for i=1:n
B(3*(i-1)+1:3*(i-1)+3,:) = A.^i;
end
B = [B(:,1:3:end) B(:,2:3:end) B(:,3:3:end)];

Here is one solution:
n = 4;
A = [1 2 9; 3 0 7; 3 1 4];
Soln = [repmat(A(:, 1), 1, n).^(repmat(1:n, 3, 1)), ...
repmat(A(:, 2), 1, n).^(repmat(1:n, 3, 1)), ...
repmat(A(:, 3), 1, n).^(repmat(1:n, 3, 1))];

Related

Building matrices using column vector and matrix in matlab

I have a column vector A (6x1) with values [6 3 10 4 2 8]'; and a matrix B (6x5) with values
B = [1 2 3 0 4 ;
3 7 8 5 0 ;
0 9 1 0 1 ;
5 0 3 1 2 ;
4 6 7 6 4 ;
3 1 2 7 3]
I want to make five matrices with size 6x2 using Matlab.
The first column is vector A
The second column is columns from B, like [A, B(first col)], [A, B(second col)]
First matrix is [6 1; 3 3; 10 0; 4 5; 2 4; 8 3];
2nd matrix is [6 2; 3 7; 10 9; 4 0; 2 6; 8 1]
... and so on
Any help I really appreciate it
You could use a loop
C = NaN( size(B,1), 2, size(B,2) );
for ii = 1:size(B,2)
C(:,:,ii) = [A, B(:,ii)];
end
This gives you a 3D array, where each slice in the 3rd dimension is a 6x2 matrix (for this example) as desired. You would access the nth slice with C(:,:,n).
You can do this slightly more concisely with arrayfun, but it's basically a loop in disguise
C = arrayfun( #(ii) [A, B(:,ii)], 1:size(B,2), 'uni', 0 );
C = cat(3, C{:} );
You could omit the cat function if you're happy with results in a cell array, where you access the nth matrix with C{n}.
You could first make a copy of the columns of A, then concatenate A and B, and reshape:
At = repmat(A, 1, size(B,2));
C = reshape([At;B], 6, 2, []);
Or oneliner:
C = reshape([repmat(A, 1, size(B,2));B], 6, 2, []);
Then retrieve your matrices with C(:,:,k)
you can use this
first_matrix=[A,B(:,1)];
second_matrix=[A,B(:,2)];
third_matrix=[A,B(:,3)];
... and so on

Reshape vector with a step and window size

I have a vector, for example
A = [1 2 3 4 5 6 7 8]
I want to "reshape" it to matrix with windowsize=4 and stepsize=2, such that the resulting matrix is
b = [ 1 3 5;
2 4 6;
3 5 7;
4 6 8 ]
You can set up an indexing matrix, then just index into A...
A = [1 2 3 4 5 6 7 8];
windowsize = 4;
stepsize = 2;
% Implicit expansion to create a matrix of indices
idx = bsxfun( #plus, (1:windowsize).', 0:stepsize:(numel(A)-windowsize) );
b = A(idx);
Note; in this case idx and b are the same, but you need the final indexing step assuming A isn't just consecutive integers in your real example.

Find and replace the rows of an array having repeated number by a fixed given row

I have a matrix having rows with repeated numbers. I want to find those rows and replace them with a dummy row so as to keep the number of rows of the matrix constant.
Dummy_row = [1 2 3]
(5x3) Matrix A
A = [2 3 6;
4 7 4;
8 7 2;
1 3 1;
7 8 2]
(5x3) Matrix new_A
new_A = [2 3 6;
1 2 3;
8 7 2;
1 2 3;
7 8 2]
I tried the following which deleted the rows having repeated numbers.
y = [1 2 3]
w = sort(A,2)
v = all(diff(t,1,2)~=0|w(:,1:2)==0,2) % When v is zero, the row has repeated numbers
z = A(w,:)
Can you please help?
bsxfun based solution -
%// Create a row mask of the elements that are to be edited
mask = any(sum(bsxfun(#eq,A,permute(A,[1 3 2])),2)>1,3);
%// Setup output variable and set to-be-edited rows as copies of [1 2 3]
new_A = A;
new_A(mask,:) = repmat(Dummy_row,sum(mask),1)
Code run -
A =
2 3 6
4 7 4
8 7 2
1 3 1
7 8 2
new_A =
2 3 6
1 2 3
8 7 2
1 2 3
7 8 2
You could use the following:
hasRepeatingNums = any(diff(sort(A, 2), 1, 2)==0, 2);
A(hasRepeatingNums,:) = repmat(Dummy_row, nnz(hasRepeatingNums), 1);
See if this works for you,
A= [ 2 3 6;
4 7 4;
8 7 2;
5 5 5;
1 8 8;
1 3 1;
7 8 2 ];
Dummy_row = [1 2 3];
b = diff(sort(A,2),1,2);
b = sum(b == 0,2);
b = b > 0;
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c;
gives,
newA =
2 3 6
1 2 3
8 7 2
1 2 3
1 2 3
1 2 3
7 8 2
Edit
Not much change is needed, try this,
Dummy_row = [1 2 3];
b = sum(A == 0,2);
b = b > 0;
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c;

Making a match-and-append code more efficient without 'for' loop

I am trying to match 1st column of A with 1st to 3rd columns of B, and append corresponding 4th column of B to A.
For example,
A=
1 2
3 4
B=
1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5
I compare A(:,1) and B(:, 1:3)
1 and 3 are in A(:,1)
1 is in the 1st, 2nd, 3rd rows of B(:, 1:3), so append B([1 2 3], 4:end)' to A's 1st row.
3 is in the 2nd and 4th rows of B(:,1:3), so append B([2 4], 4:end)' to A's 2nd row.
So that it becomes:
1 2 5 4 5 3 1 2
3 4 5 3 6 5 0 0
I could code this using only for and if.
clearvars AA A B mem mem2 mem3
A = [1 2 ; 3 4]
B = [1 2 4 5 4; 1 2 3 5 3; 1 1 1 1 2; 3 4 5 6 5]
for n=1:1:size(A,1)
mem = ismember(B(:,[1:3]), A(n,1));
mem2 = mem(:,1) + mem(:,2) + mem(:,3);
mem3 = find(mem2>0);
AA{n,:} = horzcat( A(n,:), reshape(B(mem3,[4,5])',1,[]) ); %'
end
maxLength = max(cellfun(#(x)numel(x),AA));
out = cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false))
I am trying to make this code efficient, by not using for and if, but couldn't find an answer.
Try this
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
row2 = mat2cell(permute(sum(ab==b,2),[3,1,2]),ones(1,numel(a)));
AA = cellfun(#(x)(reshape(B(x>0,4:end)',1,numel(B(x>0,4:end)))),row2,'UniformOutput',0);
maxLength = max(cellfun(#(x)numel(x),AA));
out = cat(2,A,cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false)))
UPDATE Below code runs in almost same time as the iterative code
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
df = permute(sum(ab==b,2),[3,1,2])';
AA = arrayfun(#(x)(B(df(:,x)>0,4:end)),1:size(df,2),'UniformOutput',0);
AA = arrayfun(#(x)(reshape(AA{1,x}',1,numel(AA{1,x}))),1:size(AA,2),'UniformOutput',0);
maxLength = max(arrayfun(#(x)(numel(AA{1,x})),1:size(AA,2)));
out2 = cell2mat(arrayfun(#(x,i)((cat(2,A(i,:),AA{1,x},zeros(1,maxLength-length(AA{1,x}))))),1:numel(AA),1:size(A,1),'UniformOutput',0));
How about this:
%# example data
A = [1 2
3 4];
B = [1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5];
%# rename for clarity & reshape for algorithm's convenience
needle = permute(A(:,1), [2 3 1]);
haystack = B(:,1:3);
data = B(:,4:end).';
%# Get the relevant rows of 'haystack' for each entry in 'needle'
inds = any(bsxfun(#eq, haystack, needle), 2);
%# Create data that should be appended to A
%# All data and functionality in this loop is local and static, so speed
%# should be optimal.
append = zeros( size(A,1), numel(data) );
for ii = 1:size(inds,3)
newrow = data(:,inds(:,:,ii));
append(ii,1:numel(newrow)) = newrow(:);
end
%# Now append to A, stripping unneeded zeros
A = [A append(:, ~all(append==0,1))]

how to get values of a matrix in MATLAB where the indices are given in a nx2 array

I have a matrix A of size nRows x nCols.
I have a nx2 matrix B which contains indices of the matrix A.
I want to get the values of A at the indices given in B.
lets say,
B = [1, 2;
2, 3;
3, 4]
A(1,2) = 1
A(2,3) = 2
A(3,4) = 1
I want to know any Matlab command which gives the following, given A and B (I don't want to use loops):
[1 2 1]
I guess this is what you are looking for:
A(sub2ind(size(A),B(:,1),B(:,2)))
This is what you want:
A = [1,2; 3, 4; 5, 6; 7,8; 9,0]; % this is your N by 2 matrix
B = [1,1; 1,2; 2,1; 3, 1; 4,2]; % these are your indexes
A(sub2ind(size(A), B(:,1), B(:,2)))
A =
1 2
3 4
5 6
7 8
9 0
B =
1 1
1 2
2 1
3 1
4 2
ans =
1
2
3
5
8