How to combine row and Column with different size in a cell array into matrix in MATLAB - matlab

How to efficiently combined cell array v row and Column with different size into a matrix, filling the vectors with 0?
for For example, if I have
A= {[1;2;3] [1 2 ; 1 3; 2 3] [1 2 3]};
I'd like to get either:
A=[1 0 0
2 0 0
3 0 0
1 2 0
1 3 0
2 3 0
1 2 3]

You can use simply padarray to pad your arrays with zeros before vertcat them:
B = padarray(A{1},[0 3-size(A{1},2)],'post')
C = padarray(A{2},[0 3-size(A{2},2)],'post')
D = padarray(A{3},[0 3-size(A{3},2)],'post')
%//Note the 3-size(A{1},2)... The 3 comes from the number of columns you want your final matrix to be, and it cannot be smaller than the maximum value of size(A{N},2) in your case it is 3, since A{3} is 3 columns wide.
result = vertcat (B,C,D)
result =
1 0 0
2 0 0
3 0 0
1 2 0
1 3 0
2 3 0
1 2 3
you can write a loop to iterate through your cell or use a cellfun to parallelize.
In a simple loop, it looks like:
result = [];
for t = 1:size(A,2)
B = padarray(A{t},[0 3-size(A{t},2)],'post');
result = vertcat(result,B);
end

Related

Rearranging the non zero entries in a tensor into a matrix

I have a NxNx5 array T that I would like to convert into a Rx5 array TT such that the following condition is satisfied (where R is the number of non-zero entries of the array T(:,:,1)):
If T(i,j,1) == 0 then we ignore. If T(i,j,1) != 0 then I would like a row of TT whose entry is
[T(i,j,1) T(i,j,2) T(i,j,3) T(i,j,4) T(i,j,5)]
Note that T(i,j,k) (k = 2,3,4,5) could be zero. For example,
If
T(3,2,1) = 3
then I would like a row of TT to be
[3 0 2 1 5].
Some notes:
The entries of TT are all integers.
The entries accent in order column wise. i.e the first column of TT(:,:,1) maybe
[1 2 0 0 3 4 0 0 0 5 6]'
then the next column
[7 8 0 0 0 0 0 9 10 11 12]'
I think this does what you want:
ind = find(T(:,:,1));
ind = bsxfun(#plus, ind(:), (0:size(T,3)-1)*size(T,1)*size(T,2));
result = T(ind);
This will do it:
clear
rng(343)
N=7;
K=5;
T=randi([0,4],[N,N,K])
TT=reshape(T,[N*N,K])
TT(T(:,1)==0,:)=[] %delete rows with first col equal to 0

Transform a matrix to a stacked vector where all zeroes after the last non-zero value per row are removed

I have a matrix with some zero values I want to erase.
a=[ 1 2 3 0 0; 1 0 1 3 2; 0 1 2 5 0]
>>a =
1 2 3 0 0
1 0 1 3 2
0 1 2 5 0
However, I want to erase only the ones after the last non-zero value of each line.
This means that I want to retain 1 2 3 from the first line, 1 0 1 3 2 from the second and 0 1 2 5 from the third.
I want to then store the remaining values in a vector. In the case of the example this would result in the vector
b=[1 2 3 1 0 1 3 2 0 1 2 5]
The only way I figured out involves a for loop that I would like to avoid:
b=[];
for ii=1:size(a,1)
l=max(find(a(ii,:)));
b=[b a(ii,1:l)];
end
Is there a way to vectorize this code?
There are many possible ways to do this, here is my approach:
arotate = a' %//rotate the matrix a by 90 degrees
b=flipud(arotate) %//flips the matrix up and down
c= flipud(cumsum(b,1)) %//cumulative sum the matrix rows -and then flip it back.
arotate(c==0)=[]
arotate =
1 2 3 1 0 1 3 2 0 1 2 5
=========================EDIT=====================
just realized cumsum can have direction parameter so this should do:
arotate = a'
b = cumsum(arotate,1,'reverse')
arotate(b==0)=[]
This direction parameter was not available on my 2010b version, but should be there for you if you are using 2013a or above.
Here's an approach using bsxfun's masking capability -
M = size(a,2); %// Save size parameter
at = a.'; %// Transpose input array, to be used for masked extraction
%// Index IDs of last non-zero for each row when looking from right side
[~,idx] = max(fliplr(a~=0),[],2);
%// Create a mask of elements that are to be picked up in a
%// transposed version of the input array using BSXFUN's broadcasting
out = at(bsxfun(#le,(1:M)',M+1-idx'))
Sample run (to showcase mask usage) -
>> a
a =
1 2 3 0 0
1 0 1 3 2
0 1 2 5 0
>> M = size(a,2);
>> at = a.';
>> [~,idx] = max(fliplr(a~=0),[],2);
>> bsxfun(#le,(1:M)',M+1-idx') %// mask to be used on transposed version
ans =
1 1 1
1 1 1
1 1 1
0 1 1
0 1 0
>> at(bsxfun(#le,(1:M)',M+1-idx')).'
ans =
1 2 3 1 0 1 3 2 0 1 2 5

Permute the Matrix with Given Index

Given A is symmetry matrix with size n and
A =
1 2 3 4 5 % The Position
1 [0 5 2 4 1
2 5 0 3 0 2
3 2 3 0 0 0
4 4 0 0 0 5
5 1 2 0 5 0]
B is a row vector that permute the matrix A row and column
B = [2 4 1 5 3]
The output that I want is
C =
2 4 1 5 3 % The New Position given by Matrix B
2 [0 0 5 2 3
4 0 0 4 5 0
1 5 4 0 1 2
5 2 5 1 0 0
3 3 0 2 0 0]
I can get the output by using simple for loop
index = [2,4,1,5,3];
C = zeros(5,5);
for i = 1:5
for j = 1:5
% Position of in square matrix n
% (i,j) = (i-1)*n + j
C(i,j) = A((index(i)-1)*5+index(j));
end
end
However, if I want to permute a matrix with size 80x80, then I need to run 1600 times in order to get the output.
Is there any simple trick to do it instead of using for loop?
You should be able to rearrange your matrices as follows:
C = A(index,index);
This rearranges each dimension according to the index variable independently.

Select certain elements from a vector and create a new vector with those elements in Matlab?

I have a vector 'Y' which looks something like this:
[1 1 1 0 1 2 2 2 2]
I use the Y(Y>1) command to get all elements greater than 1, in this case, all elements = 2. How do I then create a new vector based off all the elements that the Y(Y>1) command gave me?
So I'd like to end up with
X = [2 2 2 2]
Any help much appreciated.
You did answer your own question by Y(Y>1) :
>> y = [1 1 1 1 1 0 0 0 2 2 2 2 2]
y =
1 1 1 1 1 0 0 0 2 2 2 2 2
>> x=y(y>1)
x =
2 2 2 2 2
because (y>1) returns a array of logical values with the size of y containing the result of the given check.
>> (y>1)
ans =
0 0 0 0 0 0 0 0 1 1 1 1 1
you can then use this array to address data in your data array, all points where the logical array is 1 will be returned

Find position of vector in matrix [duplicate]

This question already has answers here:
General method to find submatrix in matlab matrix
(3 answers)
Closed 8 years ago.
I have the vector:
1 2 3
and the matrix:
4 1 2 3 5 5
9 8 7 6 3 1
1 4 7 8 2 3
I am trying to find a simple way of locating the vector [1 2 3] in my matrix.
A function returning either coordinates (Ie: (1,2:4)) or a matrix of 1s where there is a match a 0s where there isn't, Ie:
0 1 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
So far, the only function I've found is is 'ismember', which however only tells me if the individual components of the vector appear in the matrix. Suggestions?
Use strfind with a linearized version of the matrix, and then convert linear indices to subindices. Care should be taken to remove matches of the vector spanning different rows.
mat = [1 2 3 1 2 3 1 2;
3 0 1 2 3 5 4 4]; %// data
vec = [1 2 3]; %// data
ind = strfind(reshape(mat.',[],1).', vec);
[col row] = ind2sub(fliplr(size(mat)), ind);
keep = col<=size(mat,2)-length(vec)+1; %// remove result split across rows
row = row(keep);
col = col(keep);
Result for this example:
>> row, col
row =
1 1 2
col =
1 4 3
meaning the vector appears three times: row 1, col 1; row 1, col 4; row 2, col 3.
The result can be expressed in zero-one form as follows:
result = zeros(fliplr(size(mat)));
ind_ones = bsxfun(#plus, ind(keep).', 0:numel(vec)-1);
result(ind_ones) = 1;
result = result.';
which gives
>> result
result =
1 1 1 1 1 1 0 0
0 0 1 1 1 0 0 0
One way to get the starting location of the vector in the matrix is using colfilt:
>> A = [1 2 3 1 2 3 1 2; ...
3 0 1 2 3 5 4 4]; % matrix from Luis Mendo
>> T = [1 2 3];
>> colFun = #(x,t) all(x==repmat(t,1,size(x,2)),1);
>> B = colfilt(A,size(T),'sliding',colFun,T(:))
B =
0 1 0 0 1 0 0 0
0 0 0 1 0 0 0 0
That gives a mask of the center points, which translate to (row,col) coordinates:
>> [ii,jj]=find(B);
>> locs = bsxfun(#minus,[ii jj],floor((size(T)-1)/2))
locs =
1 1
2 3
1 4