How to get row and column of actual element in Octave/MatLab - matlab

I'm trying to get the row of the actual element (indX) in a matrix when I use this
matrix2 = matrix .* indX;
Suppose that matrix = ones(2,2)
I'm waiting matrix2 with these values [1 1; 2 2]
I can use "for" for this
[rows columns] = size(matrix) for (indX=0; indX<rows; indX++) matrix2(indX,:) = matrix(indX,:) .* indX;endfor
Is it possible to get the indX without make use of "for" ?
If yes, how can I do that ?

You can use bsxfun:
matrix2 = bsxfun(#times, (1:size(matrix,1))', matrix); %'
matrix =
4 2
3 3
4 1
>> bsxfun(#times, (1:size(matrix,1))', matrix ), % '
ans =
4 2
6 6
12 3

Related

How to get all submatrixes(2x2) from any square matrix using function and then make a new matrix with maximum values from the submatrixes

For example I have this matrix(3x3) and I want to make a new 2x2 matrix with the max values from all the submatrixes :
𝐴 = [
5 4 6
3 2 3
8 8 9
first submatrix:
[5 4
3 2 ]
max value=5
second submatrix:
[4 6
2 3]
max value=6
third submatrix:
[3 2
8 8 ]
max value=8
fourth submatrix:
[2 3
8 9]
max value=9
and I want to get this matrix(2x2) that has all the max values as elements of the previous submatrixes:
NewA=[5 6
8 9]
One last thing the only thing you can use are basic things like for loops if statements....(simple solutions,begginer solutions)
Also you can't use the max function,you have to write the code for that,and the solution should work for every square matrix
Using the Image Processing Toolbox
A = [5 4 6; 3 2 3; 8 8 9];
block_size = [2 2];
NewA = reshape(max(im2col(A, block_size, 'sliding'), [], 1), size(A)-block_size+1);
How it works:
im2col(A, block_size, 'sliding') arranges each sliding submatrix of size block_size as a column;
max(..., [], 1) takes the maximum of each column;
reshape(..., size(A)-block_size+1) reshapes the result into a matrix of the appropriate size.
Note that steps 1 and 3 both use column-major order, so the maxima in the result are arranged consistently with the input data.
Without the toolbox
Using linear indexing and implicit expansion, im2col's behaviour can be emulated as follows:
A = [5 4 6; 3 2 3; 8 8 9];
block_size = [2 2];
ind_base = (1:block_size(1)).' + (0:block_size(2)-1)*size(A,1);
ind_corner = (1:size(A,1)-block_size(1)+1).'+ (0:size(A,2)-block_size(2))*size(A,2);
ind_cols = ind_base(:) + ind_corner(:).' - 1;
NewA = reshape(max(A(ind_cols), [], 1) , size(A)-block_size+1);
The three variables ind_base, ind_corner and ind_cols have the following interpretation:
ind_base defines the linear indices of the first (uppermost, leftmost) submatrix;
ind_corner defines the linear indices of the upper-left corner of each submatrix;
ind_cols contains the linear indices of each submatrix arranged as columns.
Since the sub-matrices are 2x2 you can manually compute the max:
B = max(max(max(A(1:end-1, 1:end-1), A(1:end-1, 2:end)), A(2:end, 1:end-1)), A(2:end, 2:end));
or
B = max(cat(3, A(1:end-1, 1:end-1), A(1:end-1, 2:end), A(2:end, 1:end-1), A(2:end, 2:end)), [], 3);
If A is a square matrix both methods can be written more compact as:
n = size(A, 1);
x = 1:n-1;
y = 2:n;
B = max(max(max(A(x,x), A(x,y)), A(y,x)), A(y,y));
B = max(cat(3, A(x,x), A(x,y), A(y,x), A(y,y)), [], 3);
Using For-Loops (sliding window method)
Uses a set of nested for-loops to grab a neighbourhood of 4 (2 by 2). The position of the neighbourhood it relative to the variables Row_Index and Column_Index which are incremented/index the for-loop.
A = [5 4 6;
3 2 3;
8 8 9];
[Number_Of_Rows,Number_Of_Columns] = size(A);
Result = zeros(Number_Of_Rows-1,Number_Of_Columns-1);
for Row_Index = 1: Number_Of_Rows - 1
for Column_Index = 1: Number_Of_Columns - 1
Window = A(Row_Index:Row_Index+1,Column_Index:Column_Index+1);
Maximum = Window(1);
for Index = 2: 4
if Window(Index) > Maximum
Maximum = Window(Index);
end
end
Result(Row_Index,Column_Index) = Maximum;
end
end
Result
Ran using MATLAB R2019b

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 ;)

MATLAB multidimensional array

I have been trying to use the multidimensional array function to store NxN vectors of length n in each (i,j) entry of a 3d matrix of NxNxn dimensions.
My code looks like:
a=zeros(N,N,n);
a(i,j,:)=v_ij; %here v is a vector of length n, which differs for each i,j
However when I try to extract each vector by typing e.g. a(1,1,:) I don't get a nice vector. Rather I get something like:
ans(:,:,1) = ..
ans(:,:,2) = ..
...
I don't understand why it says ans(:,:)...
That's because each vector v_ij is stored along the 3rd dimension of your matrix, so when you access a(1,1,:), you are looking for a multidimensional array consisting of every value at the location (1,1) along the 3rd dimension of a.
Let's consider a simple example:
N = 2;
n = 3;
a = zeros(N,N,n);
for k = 1:N
for l = 1:N
v_kl = randi([0 10],1,n);
a(k,l,:) = v_kl;
end
end
The randomly-generated matrix a is a 2x2x3 matrix that looks like this:
a(:,:,1) =
4 1
4 10
a(:,:,2) =
0 2
0 5
a(:,:,3) =
2 2
9 5
Therefore, using a(1,1,:) is equivalent to getting the element located at (1,1) for all 3 dimensions, here it would be 4,0 and 2.
Indeed, calling a(1,1,:) yields:
ans(:,:,1) =
4
ans(:,:,2) =
0
ans(:,:,3) =
2
Benoit_11's answer plus squeeze should work, but I would like to propose a different solution.
Rather than creating a NxNxn array, why not make it nxNxN?
N = 2;
n = 3;
a = zeros(n,N,N);
for p = 1:N
for q = 1:N
v_pq = randi([0 10],1,n);
a(:,p,q) = v_pq;
if (p == 1) && (q == 1)
v_pq %// display vector at a(:,1,1)
end
end
end
a
v_pq =
3 4 8
a =
ans(:,:,1) =
3 3
4 9
8 7
ans(:,:,2) =
5 6
10 1
9 5
Now the vectors are stored along the first dimension, so [3 4 8] shows up as the first column of ans(:,:,1). To access it you would use a(:,p,q) rather than a(p,q,:):
a(:,1,1)
ans =
3
4
8

Find column locations of vector elements inside a matrix

Given a vector such as a = [2 5 9] and a matrix such as
8 11 5
b = 2 6 1
4 9 3
What's the best way to find which column of b contains each element of a? In this example I'd want an output like [1 3 2] because 2 is in the first column, 5 is in the third column, and 9 is in the second column. For my purposes it's safe to assume that a number can only appear in one column.
One approach -
[colID,~] = find(squeeze(any(bsxfun(#eq,b,permute(a,[1 3 2])),1)))
Or if you would like to avoid squeeze and any -
[~,colID,~] = ind2sub([size(b) numel(a)],find(bsxfun(#eq,b(:),a)))
Another way would be to use ismember:
A = [2 5 9];
B = [8 11 5; 2 6 1; 4 9 3];
[~, ind] = ismember(A,B);
[~, col] = ind2sub(size(B), ind)
col =
1 3 2
Another approach:
[~, index] = ismember(a, b);
[row, col] = ind2sub(size(b, 1), index);