MATLAB using MAT2CELL - matlab

i have the following matrices
letter=[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ...
a b c d e f g h ii jj k l m o p q r s t u v w x y z];
number=[one two three four five six seven eight nine zero];
character =[number letter];
Character becomes a matrix of 42 by 1464, but i would like to break it into cells of 42 by 24 using mat2cell.
How can i please do it, every time i try i get an error????

The example matrices you give don't make much sense given the problem you describe in the text. If you have a matrix of size 42-by-1464, and you want to use MAT2CELL to break it up into a cell array containing elements that are 42-by-24, you can do the following:
mat = repmat('a',42,1464); %# A sample character matrix containing all 'a's
[nRows nCols] = size(mat); %# Get the number of rows and columns in mat
nSubCols = 24; %# The number of desired columns in each submatrix
cellArray = mat2cell(mat,nRows,nSubCols.*ones(1,nCols/nSubCols));
The second input to MAT2CELL defines how the rows will be broken up among cells along the row dimension. In this case, a single value of 42 (i.e. nRows) indicates that the resulting cell array will have one row and the cells will contain matrices with 42 rows.
The third input to MAT2CELL defines how the columns will be broken up among cells along the column dimension. In this case, it is a 61 element (i.e. nCols/nSubCols) row vector whose elements all contain the number 24 (i.e. nSubCols). This indicates that the resulting cell array will have 61 columns and the cells will contain matrices with 24 columns.
The net result is that cellArray ends up being a 1-by-61 cell array where each cell contains a 42-by-24 submatrix of mat.
The above works when nCols is an exact multiple of nSubCols. If it isn't, then you will have to distribute columns to your cells in a heterogeneous manner (i.e. each cell may have a different number of columns in its submatrix). Some ways to deal with such a situation are discussed in this other SO question.

Related

Simplify how to find unique rows of a Matlab array

I would like your help to vectorise (or, more generally, make more efficient) a Matlab code where:
Step 1: I construct a matrix C of size sgxR, where each row contains a sequence of ones and zeros, according to whether certain logical conditions are satisfied.
Step 2: I identify the indices of the unique rows of C.
I now describe the code in more details.
Step 1: Creation of the matrix C. I divide this step in 3 sub-steps.
Step 1.a: Create the 1x3 cell U_grid. For j=1,2,3, U_grid{j} is a sg x K matrix of numbers.
clear
rng default
n_U_sets=3; %This parameter will not be changed
sg=4; %sg is usually quite large, for instance 10^6
K=5; %This parameter can range between 3 and 8
Ugrid=cell(n_U_sets,1);
for j=1:n_U_sets
Ugrid{j}=randn(sg,K);
end
Step 1.b: For each g=1,...,sg
Take the 3 rows Ugrid{1}(g,:), Ugrid{2}(g,:), Ugrid{3}(g,:).
Take all possible 1x3 rows that can be formed such that the first element is from Ugrid{1}(g,:), the second element is from
Ugrid{2}(g,:), and the third element is from Ugrid{3}(g,:). There are K^3 such rows.
Create the matrix D{g} storing row-wise all possible pairs of such 1x3 rows. D{g} will have size (K^3*(K^3-1)/2)x6
This is coded as:
%Row indices of all possible pairs of rows
[y, x] = find(tril(logical(ones(K^(n_U_sets))), -1));
indices_pairs = [x, y]; %K^3*(K^3-1)/2
%Create D{g}
for g=1:sg
vectors = cellfun(#(x) {x(g,:)}, Ugrid); %1x3
T_temp = cell(1,n_U_sets);
[T_temp{:}] = ndgrid(vectors{:});
T_temp = cat(n_U_sets+1, T_temp{:});
T = reshape(T_temp,[],n_U_sets);
D{g}=[T(indices_pairs(:,1),:) T(indices_pairs(:,2),:)]; %(K^3*(K^3-1)/2) x (6)
end
Step 1.c: From D create C. Let R=(K^3*(K^3-1)/2). R is the size of any D{g}. C is a sg x R matrix constructed as follows: for g=1,...,sg and for r=1,...,R
if D{g}(r,1)>=D{g}(r,5)+D{g}(r,6) or D{g}(r,4)<=D{g}(r,2)+D{g}(r,3)
then C(g,r)=1
otherwise C(g,r)=0
This is coded as:
R=(K^(n_U_sets)*(K^(n_U_sets)-1)/2);
C=zeros(sg,R);
for g=1:sg
for r=1:R
if D{g}(r,1)>=D{g}(r,5)+D{g}(r,6) || D{g}(r,4)<=D{g}(r,2)+D{g}(r,3)
C(g,r)=1;
end
end
end
Step 2: Assign the same index to any two rows of C that are equal.
[~,~,idx] = unique(C,"rows");
Question: Steps 1.b and 1.c are the critical ones. With sg large and K between 3 and 8, they take a lot of time, due to the loop and reshape. Do you see any way to simplify them, for instance by vectorising?

Separating some part of a matrix in matlab

I have a 2m by 2 matrix called A and a 2 by m matrix called B. Let's name the product of A by B, C:
C= A*B;
which C is a 2m by m matrix. I want to find matrix F which contains some parts of C. F is a m by 2 matrix and contains elements C(1,1), C(2,1), C(3,2),C(4,2),C(5,3), C(6,3),...C(2m-1,m), C(2m,m).
For example, consider
A = [0,2;1,3;4,7;8,3;4,5;1,2]
B=[1,4,6;5,7,3]
C=A*B;
In this case:
F=[C(1,1),C(2,1);C(3,2),C(4,2);C(5,3),C(6,3)]
But I like to find F without calculating all elements of C. Because I think calculating all elements of C would be time wasting for large values of m. Could anyone suggest a way to find F in general case?
Using Indexing:
F = [C(1:2*m+2:end);C(2:2*m+2:end)]'
To find F without calculating C you can instead use:
F=cell2mat(arrayfun(#(x) A(2*x-1:2*x,:)*B(:,x), 1:m,'uniformoutput',0))'
(You must set m, A, and B as defined in the question)
Explanation:
Each row of F is the transpose of the product of a submatrix in A and a column of B. For example, the first row in F is the transpose of:
A(1:2,:)*B(:,1)
The next row is the transpose of:
A(3:4,:)*B(:,2)
etc.
So this method only calculates the necessary values, by multiplying each column of B only by the corresponding submatrix of A and avoids calculating the unused values in C.

how to check the values of each variables from a resultant matrix in matlab?

I have sum of 3 cell arrays
A=72x1
B=72x720
C=72x90
resultant=A+B+C
size of resultant=72x64800
now when I find the minimum value with row and column indices I can locate the row element easily but how can I locate the column element in variables?
for example
after dong calculations for A,B,C I added them all and got a resultant in from of <72x(720x90)> or can say a matrix of integers of size <72x64800> then I found the minimum value of resultant with row and column index using the code below.
[minimumValue,ind]=min(resultant(:));
[row,col]=find(result== minimumValue);
then row got 14 and column got 6840 value..
now I can trace row 14 of all A,B,C variables easily but how can I know that the resultant column 6480 belongs to which combination of A,B,C?
Instead of using find, use the ind output from the min function. This is the linear index for minimumValue. To do that you can use ind2sub:
[r,c] = ind2sub(size(resultant),ind);
It is not quite clear what do you mean by resultant = A+B+C since you clearly don't sum them if you get a bigger array (72x64800), on the other hand, this is not a simple concatenation ([A B C]) since this would result in a 72x811 array.
However, assuming this is a concatenation you can do the following:
% get the 2nd dimension size of all matrices:
cols = cellfun(#(x) size(x,2),{A,B,C})
% create a vector with reapiting matrices names for all their columns:
mats = repelem(['A' 'B' 'C'],cols);
% get the relevant matrix for the c column:
mats(c)
so mats(c) will be the matrix with the minimum value.
EDIT:
From your comment I understand that your code looks something like this:
% arbitrary data:
A = rand(72,1);
B = rand(72,720);
C = rand(72,90);
% initializing:
K = size(B,2);
N = size(C,2);
counter = 1;
resultant = zeros(72,K*N);
% summing:
for k = 1:K
for n = 1:N
resultant(:,counter) = A + B(:,k) + C(:,n);
counter = counter+1;
end
end
% finding the minimum value:
[minimumValue,ind] = min(resultant(:))
and from the start of the answer you know that you can do this:
[r,c] = ind2sub(size(resultant),ind)
to get the row and column of minimumValue in resultant. So, in the same way you can do:
[Ccol,Bcol] = ind2sub([N,K],c)
where Bcol and Ccol is the column in B and C, respectively, so that:
minimumValue == A(r) + B(r,Bcol) + C(r,Ccol)
To see how it's working imagine that the loop above fills a matrix M with the value of counter, and M has a size of N-by-K. Because we fill M with a linear index, it will be filled in a column-major way, so the row will correspond to the n iterator, and the column will correspond to the k iterator. Now c corresponds to the counter where we got the minimum value, and the row and column of counter in M tells us the columns in B and C, so we can use ind2sub again to get the subscripts of the position of counter. Off course, we don't really need to create M, because the values within it are just the linear indices themselves.

Set the particular row and column zeros except the diagonal elements in matlab

Lets say I am given some indices like B = [10 23 32....];
Now lets say I have a matrix A. What I want to do is for each index from B lets say i, I want to set the ith row and ith column of A to 0 except the diagonal element A(i,i)(it remains untouched).
I can do this by looping. But I want some that is based upon some matrix multiplication which is quicker than just looping.
Any ideas guys?
You can store the diagonal elements temporarily somewhere else, index into A with B to set the corresponding rows and columns to zeros and finally plug back in the diagonal elements -
%// rows in A
rows = size(A,1);
%// Store the diagonal elements temporarily somewhere else
tmp_diagA = A(1:rows+1:end);
%// Set the ith rows and cols (obtained from B) to zero
A(B,:)=0;
A(:,B)=0;
%// Plug back in the diagonal elements in place
A(1:rows+1:end) = tmp_diagA;
Function calls are supposed to be expensive in MATLAB and we have almost have no function calls in this code, so I am hoping it to be fast enough.
One option you have is:
create the linear indexes of the diagonal elements:
[I, J]=size(A);
idx=sub2ind([I,J], B, B);
Set the horizontals and verticals to 0 and replace the diagonal elements:
NewA=A;
NewA(B, :)=zeros(numel(B),J);
NewA(:, B)=zeros(I,numel(B));
NewA(idx)=A(idx);
For square A:
b = zeros(size(A,1),1);
b(B) = B;
A = A.*bsxfun(#eq, b, b.')
For general A:
b1 = zeros(size(A,1),1);
b1(B) = B;
b2 = zeros(1,size(A,2));
b2(B) = B;
A = A.*bsxfun(#eq, b1, b2);
Suppose,
B=[10 23 32 12 15 18 20]
M=true(6)
M(B)=false %making the indexed elements false
M=or(M,diag(true(size(M,1),1))) %keep the diagonal elements one
% creating a matrix which has zero in ith row and ith column and diagonal has ones
M1=and(bsxfun(#or,bsxfun(#and,repmat(min(M,[],2),1,size(M,2)),min(M,[],1)),diag(true(size(M,1),1))),M)
%Now just multiply M1 with your matrix A, and you are done.
newA=A.*M1
You can combine above two lines in one, but I prefer them disjoint for readability purposes.

How can I extract n elements from each m-by-m window of a matrix without using loops in MATLAB?

I have a matrix and 2 parameters. The first parameter n is the number of elements to be selected. The second is the window size m.
I want to select n number of elements from every m-by-m window from the matrix. As a result we will have a p-by-q cell array where p is matrix_height/m and q is matrix_width/m.
Each element of the cell array contains the n greatest numbers from the corresponding window. It does not necessarily need to be a cell array, it can be anything that will store the necessary data.
One way to do this is by first finding all the unique m-by-m submatrices of your matrix using the function IM2COL, then sorting each column in descending order using the function SORT, and finally extracting the top n rows. If your initial matrix is A and your output matrix is B, this is what it would look like:
B = sort(im2col(A,[m m],'distinct'),1,'descend');
B = B(1:n,:); %# Get the top n values
Note that B will be an n-by-m^2 matrix. If you want to turn this into a p-by-q cell array, you can do this using the functions NUM2CELL and RESHAPE:
nBlocks = ceil(size(A)./m); %# The number of blocks in each dimension
B = reshape(num2cell(B,1),nBlocks(1),nBlocks(2));
EDIT:
If you also want to get the indices of each value with respect to the input matrix A, that is a bit more complicated. You can do it by getting the second output from SORT, which in this case will be the linear indices of the values within each m-by-m submatrix. You can convert these to subscripts using the function IND2SUB, then shift the row and column indices to account for the position of each m-by-m block:
[B,index] = sort(im2col(A,[m m],'distinct'),1,'descend');
B = B(1:n,:); %# Get the top n values
index = index(1:n,:); %# Get the top n values
[r,c] = ind2sub([m m],index); %# Convert linear indices to subscripts
nBlocks = size(A)./m; %# The number of blocks in each dimension
r = r+repmat(0:m:(nBlocks(1)-1)*m,n,nBlocks(2)); %# Shift the row indices
c = c+kron(0:m:(nBlocks(2)-1)*m,ones(n,nBlocks(1))); %# Shift the column indices
And now you can collect the row indices, column indices, and values together into a cell array using the functions MAT2CELL and RESHAPE:
B = mat2cell([r(:) c(:) B(:)],n.*ones(1,size(B,2)));
B = reshape(B,nBlocks(1),nBlocks(2));
Alternatively, you can create a structure array instead of a cell array using the functions NUM2CELL, STRUCT, and RESHAPE:
B = struct('rowIndices',num2cell(r,1),...
'colIndices',num2cell(c,1),...
'values',num2cell(B,1));
B = reshape(B,nBlocks(1),nBlocks(2));
NOTE:
The function IM2COL will pad partial blocks with zeroes in the event that a dimension of A is not an even multiple of m. If any of this zero-padding appears in the top n values for a block, one or both of the corresponding row and column indices will be out of range (i.e. have a value larger than the size of that dimension for the matrix A). Thus by checking that the row and column indices are in range you can make sure you are not including any of the zero-padding in your subsequent analysis.