Comparing a cell with a vector in Matlab - arrays

I have a cell A in Matlab of dimension 1x3, e.g.
A={{1,2,3,4} {5,6} {7,8,9} }
A contains all the integers from 1 to n in increasing order. In the example n=9. However, the number of elements within each sub-cell can be different. Each sub-cell is non-empty.
Consider the vector B of dimension nx1 containing some integers from 1 to n in increasing order (repetitions are allowed), e.g.
B=[1 1 2 2 4 7 7 8 9]'
I want to construct (without using loops) the vector C of dimension nx1 such that each C(i) tells which sub-cell of A B(i) belongs to. In the example
C=[1 1 1 1 1 3 3 3 3]'

With that structure, A is uniquely determined by the number of elements of each of its cells, and the result can be obtained as
C = sum(bsxfun(#gt, B, cumsum(cellfun(#numel, A))), 2)+1;

I don't know whether it's faster than for loops, but how about
C = arrayfun(#(b) find(cellfun(#(a) any(cell2mat(a) == b), A)), B);
Explanation: pick each element b in B; then pick every sub-cell a in A and check for equality with b, return the index of sub-cell b is a member of.

Related

Extracting positions of elements from two Matlab vectors satisfying some criteria

Consider three row vectors in Matlab, A, B, C, each with size 1xJ. I want to construct a matrix D of size Kx3 listing every triplets (a,b,c) such that:
a is the position in A of A(a).
b is the position in B of B(b).
A(a)-B(b) is an element of C.
c is the position in C of A(a)-B(b).
A(a) and B(b) are different from Inf, -Inf.
For example,
A=[-3 3 0 Inf -Inf];
B=[-2 2 0 Inf -Inf];
C=[Inf -Inf -1 1 0];
D=[1 1 3; %-3-(-2)=-1
2 2 4; % 3-2=1
3 3 5]; % 0-0=0
I would like this code to be efficient, because in my real example I have to repeat it many times.
This question relates to my previous question here, but now I'm looking for the positions of the elements.
You can use combvec (or any number of alternatives) to get all pairings of indices a and b for the corresponding arrays A and B. Then it's simply a case of following your criteria
Find the differences
Check which differences are in C
Remove elements you don't care about
Like so:
% Generate all index pairings
D = combvec( 1:numel(A), 1:numel(B) ).';
% Calculate deltas
delta = A(D(:,1)) - B(D(:,2));
delta = delta(:); % make it a column
% Get delta index in C (0 if not present)
[~,D(:,3)] = ismember(delta,C);
% If A or B are inf then the delta is Inf or NaN, remove these
idxRemove = isinf(delta) | isnan(delta) | D(:,3) == 0;
D(idxRemove,:) = [];
For your example, this yields the expected results from the question.
You said that A and B are at most 7 elements long, so you have up to 49 pairings to check. This isn't too bad, but readers should be careful that the pairings can grow quickly for larger inputs.

Compute the difference matrix between a matrix and another matrix in MATLAB

Given a matrix A in matlab with:
3 1
4 5
7 8
and another matrix B which could be referred to as some reference points (each row is reference point that is to be compared to each row of A),
1 1
1 2
I need to compute a matrix C, such that
4 5
25 18
85 72
Where each row of C is the difference (squared L2 norm) between each row of A and the rows of B. One possible way to do this in MATLAB is to first create a zero matrix C, C = zeros(5,2), and then use double for-loops to fill in the appropriate value. Is there any other efficient/simpler way in MATLAB?
Find the code snippet below
C = zeros(5,2)
for i = 1:rows
for j = 1:rows2
C(i,j) = (norm(A(i,:)-B(j,:)))^2
end
end
A solution similar to ThomasIsCoding's, but generalized to any number of dimensions (=columns). Thomas' answer requires A and B to have exactly 2 columns to use the complex representation. Here, we use a 3rd array dimension instead of complex values:
n = 3; % number of spatial dimensions for computing the L2 norm
A = 10*rand(20,n);
B = 10*rand(4,n);
C = sum((reshape(A,[],1,n) - reshape(B,1,[],n)).^2,3)
First we reshape A, such that its rows remain rows, but its columns are arranged along the 3rd array dimension. We reshape B similarly, but its rows become columns, and its columns are moved to the 3rd dimension. This arrangement of the first two dimensions match that of the output C.
Next we take the difference (using implicit singleton expansion, for older versions of MATLAB you'd need to use bsxfun), square, and sum along the 3rd dimension.
Maybe you can try bsxfun like below
A = [3,1; 4,5;7,8];
B = [1,1;1,2];
% you can first rewrite A and B in complex coordinates to simplify the computation, and then compute difference of two complex values
C = abs(bsxfun(#minus,A*[1;1j],transpose(B*[1;1j]))).^2;
and you will get
C =
4.0000 5.0000
25.0000 18.0000
85.0000 72.0000

How to create a matrix from product of all elements in two arrays?

I was reading the documentation for matlab on element-wise multiplication and I came across this example:
Create a row vector a and a column vector b, then multiply them. The
1-by-3 row vector and 6-by-1 column vector combine to produce a 6-by-3
matrix with all combinations of elements multiplied.
The documentation sure showed the output, but how did they get to that output matrix of size6,3? Which was obtained from multiplying a column vector b of size 6,1, and a row vector a of size 1,3 using the methods explained in the document.
This is called broadcasting. When one dimension is 1 while the other is bigger, the unit dimension is expanded, as if with repmat:
6 1 : column
1 3 : row
------
6 3 : result
Given
a = 1:3
b = [1:6]'
a .* b
is roughly equivalent to
a2 = repmat(a, 6, 1)
b2 = repmat(b, 1, 3)
a2 .* b2
But of course broadcasting is much more memory efficient.

Sum of all the elements of 3 different arrays

I want and optimized algorithm to find sum of each and every element of array.
for example let 3 array:
a = [1,2,3,4];
b = [5,6];
c = [8,9];
then final sum will be equal to:
sum(1,5,8)+sum(1,5,9)+sum(1,6,8)+sum(1,6,9)+sum(2,5,8)...+sum(4,6,9)
I tried doing but the algorithm I used had time complexity O(n^3), so I want anything less than this complexity.
Here is my algorithm:
sum = 0
for(i=0;i<a.size();i++)
for(j=0;j<b.size();j++)
for(k=0;k<c.size();k++)
sum = sum+a[i]+b[j]+c[k];
For this example, a, b and c have 4, 2 and 2 elements respectively. If you want to add them in every combination, there will be 4 * 2 * 2 = 16 terms to add. In those terms, each element of a will appear 4 times, because it will be added to 2 * 2 = 4 combinations of elements of b and c. Similarly, each element of b (or c) will appear 8 times, because it will be added to each 4 * 2 = 8 combinations of each elements of a and c (or b).
So, in the final sum, each element of a will appear 4 times and each element of b and c will appear 8 times. Once you figure that out, you can do fewer number of multiplications and additions to get the result.(Just sum of elements of individual arrays and then multiply these sums by 4 , 8 and 8 respectively).
Each element of a will appear in sums with each element of b and each element of c.
This means that every element in a will appear in a number of sums equal to b.length * c.length.
This is also easy to see from the brute force pseudo-code: (modified for readability)
for i = 0 to a.length
for j = 0 to b.length // happens once for each i
for k = 0 to c.length // happens b.length times for each i
sum += a[i] + ... // happens b.length * c.length times for each i
Generalising this, we come up with the following algorithm:
Sum all elements a, multiply the result by b.length * c.length.
Sum all elements b, multiply the result by a.length * b.length.
Sum all elements c, multiply the result by a.length * b.length.
Return the above three values added together.
This is an O(n) algorithm, where n is the total number of elements or average number of elements per array.

Submatrix / vector contingent on values in array

I have a 3D matrix A of size 20x500x68. I have two vectors carrying information regarding this matrix which are:
B (containing zeros and ones) of size 1x68 and
C (containing numbers from 1 to 3) of size 1x68
(in length both B and C correspond to the third dimension of A).
I would like to create a "sub matrix" of A only of that third dimension where B==1 and C==3.
Schematically:
[sub matrix of A] = A (B = 1, C = 3)
Is there any way to do this without a loop?
SMA = A(:,:,B==1 & C==3)
%This submatrix contains all rows and columns of that third dimension of A
%where B equals 1 and C equals 3

Resources