Index array of every element in MATLAB? - matlab

This might be a basic question.
To find out the maximum value and its index in array in MATLAB, I have used this code:
A = [1 2 3; 4 5 6; 7 8 9]
[val, idx] = max(A, [], 2);
Now, how can I find the index array of all the element (not finding maximum)?

May be you are talking bout subindices and global indices. Read about sub2ind and ind2sub. Check the below demo:
A = [1 2 3; 4 5 6; 7 8 9] ;
[m,n] = size(A) ;
% sub indices
[J,I] = meshgrid(1:m,1:n) ;
% global indices
idx = sub2ind(size(A),I,J)

Related

how to find the order of elements in array in Matlab?

If I have an array of A = [10 1 5 20] I want a program to find indexes of the elements. In this case Idx = [3 1 2 4]. I am using [~,Idx]=sort([10 1 5 20]) and get the following:
Idx =
2 3 1 4
It's totally not what I expected. I even don't understand how the program got those numbers.
It is simple:
A = [10 1 5 20];
[~, Idx] = sort(A);
[~, orders] = sort(Idx);
% orders
% [3 1 2 4]
orders is your answer. You need to get the indices of sorted Idx.
Note that Idx(i) represents the index of i-th element in the original array A.

Extract values from 2d array with indices from another array (without loops)

I have an array [2; 3] and a matrix [ 1 3 4 5; 2 4 9 2].
Now I would like to extract the second element from the first row and the third element from the second row and thus obtain [3 ; 9]. I managed it to do it with a loop, but since I'm working with much larger arrays, I would like to avoid these.
You can use sub2ind to convert each of the column subscripts (along with their row subscripts) into a linear index and then use that to index into your matrix.
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
% Compute the linear index using sub2ind
inds = sub2ind(size(A), (1:numel(cols)).', cols);
B = A(inds)
% 3
% 9
Alternately, you could compute the linear indices yourself which is going to be more performant than sub2ind
B = A((cols - 1) * size(A, 1) + (1:numel(cols)).');
% 3
% 9
By exploiting the diag function, you can obtain an elegant one-line solution:
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
B = diag(A(:,cols))
% 3
% 9
Here is what diag(A(:,cols)) does:
A(:,cols) selects the columns cols of A, with column k of A(:,cols) corresponding to the column cols(k) of A, giving [3 4; 4 9];
diag returns the diagonal entries of this matrix, thus returning at position k the k-th diagonal element of A(:,cols), which is A(k,cols(k)).

How to save indices and values from Matrix in Matlab?

I have a 3x3 Matrix and want to save the indices and values into a new 9x3 matrix. For example A = [1 2 3 ; 4 5 6 ; 7 8 9] so that I will get a matrix x = [1 1 1; 1 2 2; 1 3 3; 2 1 4; 2 2 5; ...] With my code I only be able to store the last values x = [3 3 9].
A = [1 2 3 ; 4 5 6 ; 7 8 9];
x=[];
for i = 1:size(A)
for j = 1:size(A)
x =[i j A(i,j)]
end
end
Thanks for your help
Vectorized approach
Here's one way to do it that avoids loops:
A = [1 2 3 ; 4 5 6 ; 7 8 9];
[ii, jj] = ndgrid(1:size(A,1), 1:size(A,2)); % row and column indices
vv = A.'; % values. Transpose because column changes first in the result, then row
x = [jj(:) ii(:) vv(:)]; % result
Using your code
You're only missing concatenation with previous x:
A = [1 2 3 ; 4 5 6 ; 7 8 9];
x = [];
for i = 1:size(A)
for j = 1:size(A)
x = [x; i j A(i,j)]; % concatenate new row to previous x
end
end
Two additional suggestions:
Don't use i and j as variable names, because that shadows the imaginary unit.
Preallocate x instead of having it grow in each iteration, to increase speed.
The modified code is:
A = [1 2 3 ; 4 5 6 ; 7 8 9];
x = NaN(numel(A),3); % preallocate
n = 0;
for ii = 1:size(A)
for jj = 1:size(A)
n = n + 1; % update row counter
x(n,:) = [ii jj A(ii,jj)]; % fill row n
end
end
I developed a solution that works much faster. Here is the code:
% Generate subscripts from linear index
[i, j] = ind2sub(size(A),1:numel(A));
% Just concatenate subscripts and values
x = [i' j' A(:)];
Try it out and let me know ;)

Extracting a specific element from each cell within cell array

I have a cell array A of size 10x10 (say). Each cell in turn contains a 5x20 matrix. I want to select (i,j) element from each cell, where (i,j) are indices within a loop. I can run 4 for loops and easily get the answer. It may even be faster as it has been discussed many times that loops could be faster than cellfun, structfun etc.
Still, is there any solution using cellfun which I can use in a loop over (i,j) and extract (i,j) element in each cell? I tried writing a function which will act as handle to cellfun but I couldn't access two-leves down i.e. A{eachCellRow,eachCellCol}(i,j).
Example:
If A={[1 2;5 6], [3 4; 6 7]; [3 4; 6 7], [9 8; 5 6]};
Then for i=1, j=1 and i=2, j=1 output should be:
B=[1 3; 3 9] and B=[5 6; 6 5]
CELL2MAT gets all the data from a cell array that consists of numeric data only, into a numeric array. So, that helped us here. For your original problem, try this -
celldim_i = 10;
celldim_j = 10;
block_size_i = 5;
block_size_j = 20;
search_i = i; %// Edit to your i
search_j = j; %// Edit to your j
A_mat = cell2mat(A);
out = A_mat(search_i+block_size_i*(0:celldim_i-1),search_j+block_size_j*(0:celldim_j-1))
The easy to use cellfun one-liner would be:
ii = 2;
jj = 1;
A = {[1 2;5 6], [3 4; 6 7]; [3 4; 6 7], [9 8; 5 6]};
B = cell2mat( cellfun( #(x) x(ii,jj), A, 'uni', 0) )
gives:
B =
5 6
6 5
Advantage over Divakar's Solution: it works also for inconsistent matrix sizes in A.
And if you want to avoid also the outer loop, another fancy two-liner:
dim = [2 2];
[II, JJ] = meshgrid( 1:dim(1), 1:dim(2) );
C = cellfun( #(y) ...
{ cell2mat( cellfun( #(x) x( real(y), imag(y) ), A, 'uni', 0) ) },...
num2cell( II(:)+1i*JJ(:) ))
gives:
>> celldisp(C)
C{1} = % ii = 1 , jj = 1
1 3
3 9
C{2} = % ii = 1 , jj = 2
2 4
4 8
C{3} = % ii = 2 , jj = 1
5 6
6 5
C{4} = % ii = 2 , jj = 2
6 7
7 6
If memory is not an issue, you can concat all matrices along a third dim; and then indexing is very easy:
%// Example data
A = {[1 2;5 6], [3 4; 6 7]; [3 4; 6 7], [9 8; 5 6]};
ii = 2;
jj = 1;
%// Compute the result B
A2 = cat(3,A{:}); %// concat along third dim
B = reshape(A2(ii,jj,:),size(A{1})); %// index A2 and reshape

Changing multiple elements (of known coordinates) of a matrix without a for loop

I have a matrix say
Z = [1 2 3;
4 5 6;
7 8 9]
I have to change its values, say at positions (2,2) and (3,1), to some specified value. I have two matrices rowNos and colNos which contain these positions:
rowNos = [2, 3]
colNos = [2, 1]
Let's say I want to change the value of elements at these positions to 0.
How can I do it without using for loop?
Use sub2ind, it'll convert your sub-indices to linear indices, which is a number pointing at one exact spot in the matrix (more info).
Z = [ 1 2 3 ; 4 5 6 ; 7 8 9];
rowNos = [2, 3];
colNos = [2, 1];
lin_idcs = sub2ind(size(Z), rowNos, colNos)
If you want to operate on all elements on a specific row and column (elements in higher dimensions that is), you can also address them using linear indexing. It only becomes a bit trickier of calculating them:
Z = reshape(1:4*4*3,[4 4 3]);
rowNos = [2, 3];
colNos = [2, 1];
siz = size(Z);
lin_idcs = sub2ind(siz, rowNos, colNos,ones(size(rowNos))); % just the first element of the remaining dimensions
lin_idcs_all = bsxfun(#plus,lin_idcs',prod(siz(1:2))*(0:prod(siz(3:end))-1)); % all of them
lin_idcs_all = lin_idcs_all(:);
Z(lin_idcs_all) = 0;
experiment a bit with sub2ind, and go through my code step-by-step to understand it.
It would've been easier if it was the first dimension you wanted to take all elements off, then you could have used the colon operator :
Z = reshape(1:3*4*4,[3 4 4]);
rowNos = [2, 3];
colNos = [2, 1];
siz = size(Z);
lin_idcs = sub2ind(siz(2:end),rowNos,colNos);
Z(:,lin_idcs) = 0;
Use sub2ind with multiple entries for rows and columns
Z(sub2ind(size(Z), rowNos, colNos))=0
Example:
Z = [1 2 3;
4 5 6;
7 8 9];
rowNos = [2, 3];
colNos = [2, 1];
Z(sub2ind(size(Z), rowNos, colNos))=0
Z =
1 2 3
4 0 6
0 8 9
You would like to do this
z(rowNos, colNos)
but you can not - MATLAB does a Cartesian product of the indices. You can do this trick
idx=(colNos-1)*size(z, 1)+rowNos;
z(idx)=0
Flatten the z-matrix and access it through a linear index, which is a combination of rowNos and colNos. Remember that MATLAB flattens the matrix by columns (column-based matrix storage).