MATLAB: Accessing Multidimensional Cell Matrix Index - matlab

I have cell matrix which the dimensions are changing according to user input. As a user, I want to use one dimension's certain index meanwhile whole the elements of the other dimensions exist. I think it is better to explain the situation with a certain example:
Assume that my cell matrix A whose sizes are 2x3x4x5x7. I want to use whole elements of 1.,3. and 4. dimension. At the same time only the 2. element of the 2. dimension and 3., 5. elements of 5. dimension. This can be achieved easily with :
A(:,2,:,:,[3 5]);
What about the case A is input of a function and dimensions are changing. How can I obtain this result with linear indexing or another way?
I know that there is no such a syntax but my situation can be described as follows:
whole_indexes = sub2ind(size(A),[:,2,:,:,[3,5]]);
A(whole_indexes)

This problem can be solved the with the code below:
size_A = size(A); % A is the matrix whose elements will be selected
whole_index = cellfun(#(x) 1:x,num2cell(size_A),'UniformOut',false); % create a cell array which includes all the possible numbers
all_sizes = cellfun(#length,whole_index); % each dimension size
%% select the desired indexes in your desired dimensions
whole_index{1} = [1 2]; % first dimension first 2 elements
whole_index{2} = [2]; % second dimension second element
all_numbers = combvec(whole_index{:}).'; % whole possibilities
all_numbers = mat2cell(all_numbers,max(size_nums),ones(1,min(size_nums))); % cell format of possibilities
comb_inds = sub2ind(all_sizes,all_numbers{:});
desired_out = A(comb_inds);
Another solution would be written like:
size_A = size(A); % A is the matrix whose elements will be selected
whole_index = cellfun(#(x) 1:x,num2cell(size_A),'UniformOut',false);
%% select the desired indexes in your desired dimensions
whole_index{1} = [1 2]; % first dimension first 2 elements
whole_index{2} = [2]; % second dimension second element
desired_out = A(whole_index{:});

Related

Obtain location of maximum inside a 3D matrix

How can I get a maximum of a three-dimensional matrix (which was previously two-dimensional and converted to a three-dimensional matrix by reshape) in MATLAB so that I can then get the position of that maximum value in the matrix?
I wrote the following code, but unfortunately the dimensions obtained for the maximum values are larger than the dimensions of the matrix.
mxshirin=max(max(frvrdin))
[X,Y,Z]=size(frvrdin)
[o,i]=find(frvrdin==mxshirin)
xo=size(o)
xi=size(i)
If frvrdin is 3D, max(max(frvrdin)) will be a 1x1x3 vector:
frvrdin = rand(3,3,3);
max(max(frvrdin))
ans(:,:,1) =
0.8235
ans(:,:,2) =
0.9502
ans(:,:,3) =
0.7547
Don't nest max() functions, simply use the 'all' switch to take the max of the entire matrix at once.
max(frvrdin,[],'all')
ans =
0.9340
If you're on an older MATLAB, use column flattening: max(frvrdin(:)).
You can't use the automated location output of max [val,idx]=max() on more than two dimensions, so use find and ind2sub:
frvrdin = rand(3,3,3);
val = max(frvrdin,[],'all'); % Find maximum over all dims
idx = find(abs(frvrdin-val)<1e-10); % Compare within tolerance
[row,col,page] = ind2sub(size(frvrdin),idx); % Get subscript indices
where row is the index into your first dimension, col into the second and finally page into the third.

Matlab: What is the most efficient way to add zero rows (or column) to a sparse matrix?

Suppose I have an N x N sparse matrix. Take for example A = speye(N).
My general question is: what is the most efficient way to add zero rows (or column) to a sparse matrix?
Adding jj columns on the right side of the matrix and/or adding ii rows at the bottom of the matrix simply changes the size of the sparse matrix. So in code this would be
N=2;
A=speye(N);
[rows,cols,vals] = find(A);
% Add ii = 3 zero rows at the bottom
% and jj = 2 zero columns at the left of A
ii = 3; jj=2;
B = sparse(rows,cols,vals,N+ii,N+jj);
Adding columns on the left and at the top, also changes the indices.
N=2;
A=speye(N);
[rows,cols,vals] = find(A);
% Add ii = 3 zero rows at the top
% and jj = 2 zero columns at the right of A
ii = 3; jj=2;
B = sparse(rows+ii,cols+jj,vals,N+ii,N+jj);
Is there a more efficient way, for either of the two cases? For example, can I skip somehow finding the non-zero elements of A?
You can add a column as you would with a standard matrix
% Create a sparse matrix
A = speye(3);
% Add a column of zeros to the end
A(:, end+1) = 0;
Note that find will still only return the 2 non-zero values, but size(A)=[2,3], i.e we've successfully added a column.
Variants:
% Still adding a column on the right, by concatenating with another sparse matrix.
% However: this is less memory efficient with A on the right hand side
A = [A, sparse(3,1)];
% Adding column on the left
A = [sparse(3,1), A]; % comma is equivalent of 'horzcat'
% Adding a row on the top
A = [sparse(1,size(A,2)); A]; % semi-colon is equivalent of 'vertcat'

Non-trivial reshape in chunks

I am trying to reshape a matrix, but not in the standard way. It is basically a "chunk" reshape. I have a column vector named matrix1 which is (T*N x 1) and a matrix named matrix2 which is TxN. I want the first N elements of the column vector matrix1 to be transposed into the first row of matrix2. Then the second chunk of N elements of vector matrix1 to be transposed into the second row of matrix2.
I know how to do it with a loop (see code below). Just wondering if there is a smarter way to do it.
T = 2;
N = 7;
matrix1 = rand(T*N,1);
matrix2 = NaN(T,N);
for t = 1:T
matrix2(t,:) = matrix1(t*N-N+1:t*N,1)';
end
Use reshape for reshaping... You literally describe a standard reshape in the text.
reshape(matrix1,N,T).'

sorting a matrix in MATLAB

I have a matrix that contains ( 6 rows, 2 columns) as shown in the attached image.
I'd like to have a new matrix (in MATLAB) that contains the second columns arranged in ascending order, but would like to keep their corresponding values in the row.
for example: the output matrix looks like this
You can do it as follows:
mat = randi(30, [6 2]); % creating the matrix
[mat(:,2),ind] = sort(mat(:,2));
mat(:,1) = mat(ind,1);
If you have access to the sortrows function, it is simpler:
mat = sortrows(mat,2);

divide the image into 3*3 blocks

I have a matrix that does not happen to have dimensions that are multiples of 3 or it might.
How can we divide the entire image into blocks of 3*3 matrices.
(Can ignore the last ones which does not come under the 3*3 multiples.
Also, the 3*3 matrices can be be saved in arrays.
a=3; b=3; %window size
x=size(f,1)/a; y=size(f,2)/b; %f is the original image
m=a*ones(1,x); n=b*ones(1,y);
I=mat2cell(f,m,n);
I have never used mat2cell to divide matrices, and thinking about it now it seems like a really good idea. As I don't have MATLAB here in this computer, I'll describe the way I do it, which does not involve mat2cell.
Ignoring the last columns and rows is easy:
d = 3; % the dimension of the sub matrix
[x,y] = size(f);
% perform integer division by three
m = floor(x/d);
n = floor(y/d);
% find out how many cols and rows have to be left out
m_rest = mod(x,d);
n_rest = mod(y,d);
% remove the rows and columns that won't fit
new_f = f(1:(end-m_rest), 1:(end-n_rest));
% this steps you won't have to perform if you use mat2cell
% creates the matrix with (m,n) pages
new_f = reshape( new_f, [ d m d n ] );
new_f = permute( new_f, [ 1 3 2 4 ] );
Now you can access the sub-matrices like this:
new_f(:,:,1,1) % returns the 1st one
new_f(:,:,3,2) % returns the one at position [3,2]
If you'd like to use mat2cell to do that, you could do something like the following:
% after creating new_f, instead of the reshape, permute
cells_f = mat2cell(new_f, d*ones(1,m), d*ones(1,n));
Then you would access it in a different way:
cells_f{1,1}
cells_f{3,2}
The cell approach I cannot test because I don't have MATLAB on this PC, but if I can recall the usage of mat2cell correctly, it should work fine.
Hope it helps :)