Subscript to linear index - matlab

M is a matrix of prime numbers from 1 to 23 (in row order)
I don't understand how the second code line replaces the diagonal entries of M with 1. I am also confused because the function sub2ind converts row/column subscript to linear index both of which has nothing to do with the value of the entry.
M = zeros(3); M(:) = primes(23); M = M'
M(sub2ind(size(M), 1:3, 1:3)) = 1

sub2ind(size(M), 1:3, 1:3) returns an array [1, 5, 9] of the linear index of entries: (1,1), (2,2), (3,3). In M(sub2ind(size(M), 1:3, 1:3)) you are accessing M as a vector, it is equivalent to writing M([1, 5, 9]) so you are accessing the matrix with linear indexing, and you are assigning the value 1 to those entries: M(sub2ind(size(M), 1:3, 1:3)) = 1 so that changes the value of those entries

Related

Find a pair of numbers in a matrix in Matlab

Given the matrix A = [6 4 1; 1 4 3; 3 4 2;7 6 8] and the array of pairs b = [4 6; 4 1; 1 6], I want to find the pairs given in b in the rows of A without a for loop.
For example, the first pairs is (4,6) or (6,4) , which occurs in the first row of A.
Assuming, you want to find the rows of A which contain the exact pairs given in b, this is how you can do it without a loop:
% Create a matrix of pairs in A
pairs = cat(3, A(:, 1:end-1), A(:, 2:end));
% Reshape b to use bsxfun
b_ = reshape(b', [1 1 size(b')]);
% Get the matches for the pairs and for the flipped pairs
indices = all( bsxfun(#eq, pairs, b_), 3) | all( bsxfun(#eq, pairs, flip(b_,3)), 3);
% Find the indices of the rows with a match
row_indices = find(squeeze(any(any(indices,4),2)));
Please refer to the reference on vectorization for more information on how to make fast computations in Matlab without loops.

3d matrix: how to use (row, column) pairs with 3rd dimension wildcard in MATLAB?

I have a 3 dimensional matrix, and a list of (row, column) pairs. I would like to extract the 2 dimensional matrix that corresponds to the elements in those positions, projected through the depth of the matrix. For instance, suppose,
>> a = rand(4, 3, 2)
a(:,:,1) =
0.5234 0.7057 0.0282
0.6173 0.2980 0.9041
0.7337 0.9380 0.9639
0.0591 0.8765 0.1693
a(:,:,2) =
0.8803 0.2094 0.5841
0.7151 0.9174 0.6203
0.7914 0.7674 0.6194
0.2009 0.2542 0.3600
>> rows = [1 4 2 1];
>> cols = [1 2 1 3];
What I'd like to get is,
0.5234 0.8765 0.6173 0.0282
0.8803 0.2542 0.7151 0.5841
maybe with some permutation of dimensions. Also, although this example has the wildcard in the last dimension, I also have cases where it's in the first or second.
I naively tried a(rows, cols, :) and got a 3d matrix where the diagonal plane is what I want. I also found sub2ind, which will extract the desired elements from the a(:,:,1) plane. I could work with one of these to get to what I want, but I'm wondering is there a more canonical, elegant, or efficient method that I'm missing?
Update
This was the solution I used, based on the answer posted below,
sz = size(a);
subs = [repmat(rows, [1, sz(3)]);
repmat(cols, [1, sz(3)]);
repelem([1:sz(3)], length(rows))];
result = a(sub2ind(sz, subs(1,:), subs(2,:), subs(3,:)));
sub2ind is pretty much what you have to use here to convert your subscripts into linear indices (apart from manually computing the linear indices yourself). You can do something like the following which will convert the rows and cols to a linear index (in a 2D slice) and then it adds an offset (equal to the number of elements in a 2D slice) to these indices to sample all elements in the third dimension.
sz = size(a);
inds = sub2ind(sz(1:2), rows, cols);
inds = bsxfun(#plus, inds, (0:(sz(3)-1)).' * prod(sz(1:2)));
result = a(inds);
And to actually compute the linear indices yourself
inds = (cols - 1) * sz(1) + rows;
inds = bsxfun(#plus, inds, (0:(sz(3) - 1)).' * prod(sz(1:2)));
result = a(inds);
Another option would be to permute your initial matrix to bring the third dimension to the first dimension, reshape it to a 2D matrix, and then use the linear index as the second subscript
% Create a new temporary matrix
anew = reshape(permute(a, [3, 1, 2]), size(a, 3), []);
% Grab all rows (the 3rd dimension) and compute the columns to grab
result = anew(:, (cols - 1) * size(a, 1) + rows);

How to index a matrix with the column maxima of other matrix

I have 2 matrices A and B.
I find the max values in the columns of A, and keep their indices in I. So far so good.
Now, I need to choose those arrays of B with the same index as stored in I. I don't know how to do this.
See below:
A = [1,2,3; 0,8,9]
B = [0,1,2; 4,2,3]
[~,I] = max(A)
h = B(I)
I need to get these values of B:
h = [0 2 3]
But the code results in a different one. How can I fix it?
A =
1 2 3
0 8 9
B =
0 1 2
4 2 3
I =
1 2 2
h =
0 4 4
Thanks in advance
The max function how you used it works like
If A is a matrix, then max(A) is a row vector containing the maximum value of each column.
so M = max(A) is equivalent to M = max(A,[],1). But rather use the third input if you're not sure.
If you use max to find the maxima in the columns of the matrix, it returns the row indices. The column indices are for your case simply 1:size(A,2) = [1 2 3].
Now you need to convert your row and column indices to linear indices with sub2ind:
%// data
A = [1,2,3; 0,8,9]
B = [0,1,2; 4,2,3]
%// find maxima of each column in A
[~, I] = max( A, [], 1 ) %// returns row indices
%// get linear indices for both, row indices and column indices
I = sub2ind( size(A), I, 1:size(A,2) )
%// index B
h = B(I)
returns:
h =
0 2 3

How do I raise a vector to a vector in MATLAB? [duplicate]

I have two vectors, X of bases and N of exponents. I want to get the matrix of all values e = xn for each x in X and n in N.
For example, the following input:
X = [2 3 4]'
N = [1 2 3]
should produce:
ans = [2 4 8; 3 9 27; 4 16 64]
Is there a way to get this without looping (just like you can get all values of x×n by using the column by row product)?
Use bsxfun:
bsxfun(#power, X, N)
This assumes that X is a column vector and N is a row vector. If you want to guarantee that, use the following syntax which is more robust:
bsxfun(#power, X(:), N(:).')
This is probably a bit sloppier than the bsxfun answer, but you could use meshgrid:
E = X.^(meshgrid(N)')
This assumes both X and N are row vectors. If both are column vectors then it becomes:
E = X.^(meshgrid(N))

Vector as column index in matrix

Given a matrix A (mxn) and a vector B (mx1) I want to create a vector C (mx1) in which each row element is the row element of A from a column indexed by B.
Is it possible to do this, without using loops?
A = [1 2; 3 4; 5 6];
B = [2 1 1].';
Then I want:
C = [2 3 5].';
Convert the column subscripts of B to linear indices and then use them to reference elements in A:
idx = sub2ind(size(A), (1:size(A, 1)).', B);
C = A(idx);
(for more information, read the part about linear indexing in this answer).