How to find the approximate numbers in two matrix? - matlab

How to find the approximate numbers in two matrix?
For example,
There are two matrixes
A=[1.567 1.679 1.366 ;
2.467 3.587 6.134 ;
3.497 5.877 9.465]
B=[3.134 5.100 7.555 ;
7.465 4.715 4.267 ;
2.347 4.111 4.503]
So in A matrix 2.467 is close to 2.347 in B matrix.
How can I find them by coding?

Create a meshgrid of all the values in A and all the values in B so we can compare them:
[Amesh,Bmesh] = meshgrid(A(:),B(:))
Now find the absolute value of the difference:
absdiff = abs(Amesh-Bmesh)
This is a matrix of the absolute difference between every value in A vs. every value in B. So the minimum value in this table is your closest match between a value in A and B. To programatically find that value:
[x,y] = find(absdiff == min(absdiff(:)))
x =
3
y =
2
This calculates the minimum value of that matrix, and then finds the x/y position of that value. In this case x is the index into matrix B and y is the index into matrix A.
>> A(y)
ans =
2.4670
>> B(x)
ans =
2.3470

Related

How to return a row vector containing the positional indices of a given number

Write a function in MATLAB called matrix_find_k that accepts a NxN matrix, m, and a value scalar value k and returns a row vector with the positional indices (i.e. (i,j) )of k within m. If the matrix doesn’t contain k, return an empty vector.
function rvector=matrix_find_k(m,k)
m=m==k
So far this is all I have. I don't know how to find the positions of all the ones that I have created in the matrix m.
Here is a possible solution using the find function - it returns a vector containing the indices of the scalar value in the matrix and returns an empty vector if the scalar value is not found:
Example Script to call function:
%Example matrix
m = [1 2 3 4;
5 6 7 8;
9 10 11 12];
k = 3; % Example value to find
rvector = matrix_find_k(m,k)
Function:
function rvector = matrix_find_k(m,k)
[i,j] = find(m == k);
rvector = [i,j];
end
Example output: (example k=3 is in row 1 column 3 of matrix m)
rvector =
1 3

Comparing matrices of different size in matlab and storing values that are close

I have two matrices A and B. A(:,1) corresponds to an x-coordinate, A(:,2) corresponds to a y-coordinate, and A(:,3) corresponds to a certain radius. All three values in a row describe the same circle. Now let's say...
A =
[1,4,3]
[8,8,7]
[3,6,3]
B =
[1,3,3]
[1, 92,3]
[4,57,8]
[5,62,1]
[3,4,6]
[9,8,7]
What I need is to be able to loop through matrix A and determine if there are any rows in matrix B that are "similar" as in the x value is within a range (-2,2) of the x value of A (Likewise with the y-coordinate and radius).If it satisfies all three of these conditions, it will be added to a new matrix with the values that were in A. So for example I would need the above data to return...
ans =
[1,4,3]
[8,8,7]
Please help and thank you in advance to anyone willing to take the time!
You can use ismembertol.
result = A(ismembertol(A,B,2,'ByRows',1,'DataScale',1),:)
Manual method
A = [1,4,3;
8,8,7;
3,6,3];
B = [1,3,3;
1,92,3;
4,57,8;
5,62,1;
3,4,6;
9,8,7]; % example matrices
t = 2; % desired threshold
m = any(all(abs(bsxfun(#minus, A, permute(B, [3 2 1])))<=t, 2), 3);
result = A(m,:);
The key is using permute to move the first dimension of B to the third dimension. Then bsxfun computes the element-wise differences for all pairs of rows in the original matrices. A row of A should be selected if all the absolute differences with respect to any column of B are less than the desired threshold t. The resulting variable m is a logical index which is used for selecting those rows.
Using pdist2 (Statistics and Machine Learning Toolbox)
m = any(pdist2(A, B, 'chebychev')<=t, 2);
result = A(m,:);
Ths pdist2 function with the chebychev option computes the maximum coordinate difference (Chebychev distance, or L∞ metric) between pairs of rows.
With for loop
It should work:
A = [1,4,3;
8,8,7;
3,6,3]
B = [1,3,3;
1,92,3;
4,57,8;
5,62,1;
3,4,6;
9,8,7]
index = 1;
for i = 1:size(A,1)
C = abs(B - A(i,:));
if any(max(C,[],2)<=2)
out(index,:) = A(i,:);
index = index + 1
end
end
For each row of A, computes the absolute difference between B and that row, then checks if there exists a row in which the maximum is less than 2.
Without for loop
ind = any(max(abs(B - permute(A,[3 2 1])),[],2)<=2);
out = A(ind(:),:);

Find the position of the minimal value of a three dimensional array in Matlab

Sorry for asking such a simple and silly question, but Matlab is really too hard to use for me. My question is just how to find the position the minimal value of a three dimensional array in Matlab.
For example, suppose I define a three dimensional array
m=zeros(2,2,2);
m(1,2,2)=-2;
The minimal value of m should be -2, located at (1,2,2). I can find the minimal value by
m0=min(min(min(m)));
But when I find its position by using
[x y z]=find(m==m0);
Instead of returning x=1, y=2 and z=2, it returns x=1, y=4 and z=1.
I appreciate if anyone would answer this question!
You can use min to find the minimum index of m and then convert it to x, y and z coordinates. There is no need to use find also.
min can be used with multiple output arguments to return the index of the minimum element. Here, I also use : to return every element of m as a column vector.
>> m=zeros(2,2,2);
>> m(1,2,2)=-2;
>> m(:)
ans =
0
0
0
0
0
0
-2
0
>> [~, ind] = min(m(:))
ind =
7
Now we have our index we need to convert it back into x, y and z coordinates. This can be done using ind2sub or manually by hand.
>> [x y z] = ind2sub(size(m), ind)
x =
1
y =
2
z =
2
You're correct. This is more complicated than it should be. The problem is that MATLAB is hardwired to work with matrices (i.e. arrays of rank 2), rather than arrays of general rank. Here's the solution:
m0 = min(m(:))
[x y z] = ind2sub(size(m), find(m(:) == m0))
Explanation:
If you type help find, you may notice that your original code was using the [rows, cols, vals] version of find, which is not what you expected.
Instead, min(m(:)) is a simplification of your min(min(min(m))). It automatically reshapes m into a rank one array (i.e. a vector).
The expression find(m(:) == m0) returns a single index for the minimum position in this reshaped vector. Finally, ind2sub converts this single index into a set of three indices, given the shape of m.

Find the maximum value of four dimensional matrix along with the indices

I am trying to find the entry of matrix Athat has the maximum value.
I have generated matrix A, how can I ask MATLAB to return the four indices in addition to the maximum value of the entry within matrix A
for i = 1:size(CB,2)
for j=1:size(CB,2)
for k=1:size(CB,2)
for l=1:size(CB,2)
A(i,j,k,l)= (abs( conj(transpose([CB(:,i); CB(:,j)]))*MATRIX* [CB(:,k); CB(:,l)])^2);
end
end
end
end
You can use a combination of max and ind2sub:
a = rand(5, 5, 5, 5);
[maxa, maxidx] = max(a(:));
[I, J, K, L] = ind2sub(size(a), maxidx);
Which we can test:
>> a(I, J, K, L) == maxa
ans =
1
The way this works is that we receive a linear index from the second output of the max command. I used the colon operator with max so our input is really one long column vector of a, and the output is the maximum value of the entire matrix, maxa, along with the location of that value in the column vector, maxidx. You can then use ind2sub with size to convert that linear index into subscripts for your matrix.
Use 1-D indexing:
[M,I] = max(A(:));
I is then the index in A where M resides (i.e., M = A(I))
Then you need to use the following to convert from 1D indexing to 4D indexing:
[a,b,c,d] = ind2sub(size(A),I);

Finding closest (not equal) rows in two matrices matlab

I have two matrices A(m X 3) and B(n X 3); where m >> n.
Numbers in B have close or equal values to numbers in A.
I want to search closest possible values from A to the values present in B in a way that at the end of search, A will reduced to (n X 3).
There are two main issues:
Only a complete row from A can be compared to a complete row in B, where numbers in each column of A and B are varying independently.
Numbers in A and B may be as close as third place of decimal (e.g. 20.101 and 20.103)
I hope I am clear in asking my question.
Does anybody know about any function already present in matlab for this thing?
Depending on how you look at the task, here are two different approaches
Minimum Distance to Each Row in Second Matrix
Two ways to look at this: (1) closest point in A for each point in B, or (2) closest point in B for each point in A.
Closest point in A
For each point in B you can find the closest point in A (e.g. Euclidean distance), as requested in comments:
% Calculate all MxN high-dimensional (3D space) distances at once
distances = squeeze(sum(bsxfun(#minus,B,permute(A,[3 2 1])).^2,2));
% Find closest row in A for each point in B
[~,ik] = min(distances,[],2)
Make an array the size of B containing these closest points in A:
Anew = A(ik,:)
This will implicitly throw out any points in A that are too far from points in B, as long as each point in B does have a match in A. If each point in B does not necessarily have a "match" (point at an acceptable distance) in A, then it is necessary to actively reject points based on distances, resulting in an output that would be shorter than B. This solution seems out of scope.
Closest point in B
Compute the Euclidenan distance from each point (row) in A to each point in B and identify the closest point in B:
distances = squeeze(sum(bsxfun(#minus,A,permute(B,[3 2 1])).^2,2));
[~,ik] = min(distances,[],2)
Make an array the size of A containing these closest points in B:
Anew = B(ik,:)
The size of Anew in this approach is the same as A.
Merging Similar Points in First Matrix
Another approach is to use the undocumented _mergesimpts function.
Consider this test data:
>> B = randi(5,4,3)
B =
1 4 4
2 3 4
1 3 4
3 4 5
>> tol = 0.001;
>> A = repmat(B,3,1) + tol * rand(size(B,1)*3,3)
A =
1.0004 4.0005 4.0000
2.0004 3.0005 4.0008
1.0004 3.0009 4.0002
3.0008 4.0005 5.0004
1.0006 4.0004 4.0007
2.0008 3.0007 4.0004
1.0009 3.0007 4.0007
3.0010 4.0005 5.0004
1.0002 4.0003 4.0007
2.0001 3.0001 4.0007
1.0007 3.0006 4.0004
3.0001 4.0003 5.0000
Merge similar rows in A according to a specified tolerance, tol:
>> builtin('_mergesimpts',A,tol,'average')
ans =
1.0004 4.0004 4.0005
1.0007 3.0007 4.0005
2.0005 3.0005 4.0006
3.0006 4.0004 5.0003
Merge similar rows, using B to get expected numbers
>> builtin('_mergesimpts',[A; B],tol,'first')
ans =
1 3 4
1 4 4
2 3 4
3 4 5
To replace each row of A by the closest row of B
You can use pdist2 to compute distance between rows, and then the second output of min to find the index of the minimum-distance row:
[~, ind] = min(pdist2(B,A,'euclidean')); %// or specify some other distance
result = B(ind,:);
The advantage of this approach is that pdist2 lets you specify other distance functions, or even define your own. For example, to use L1 distance change first line to
[~, ind] = min(pdist2(B,A,'cityblock'));
To retain rows of A which are closest to rows of B
Use pdist2 as above. For each row of A compute the minimum distance to rows of B. Retain the n rows of A with lowest value of that minimum distance:
[~, ii] = sort(min(pdist2(B,A,'euclidean'))); %// or use some other distance
result = A(ii(1:n),:);
Try this code -
%% Create data
m=7;
n=4;
TOL = 0.0005;
A = rand(m,3)/100;
B = rand(n,3)/100;
B(2,:) = A(5,:); % For testing that the matching part of the second row from B must be the fifth row from A
%% Interesting part
B2 = repmat(reshape(B',1,3,n),[m 1]);
closeness_matrix = abs(bsxfun(#minus, A, B2));
closeness_matrix(closeness_matrix<TOL)=0;
closeness_matrix_mean = mean(closeness_matrix,2); % Assuming that the "closeness" for the triplets on each row can be measured by the mean value of them
X1 = squeeze(closeness_matrix_mean);
[minval,minind] = min(X1,[],1);
close_indices = minind';
A_final = A(close_indices,:)