Compare two unequal matrix some specific column without using for loop - matlab

I want to compare two matrices without using a for loop. Given
A=[2 1 8;
2 4 7;
2 3 7;
3 5 2;
5 1 4;
5 6 2;
5 3 7];
B=[3 6 5;
1 4 2];
Now I want to compare col(2) two of matrix B with col(2) two of matrix A and at the same time col(3) three of matrix B and col(1) one of matrix A. Now I want to get the result from matrix A like this:
c=[2 4 7;
5 6 2];

I think #mizanbuet wants to extract rows from A where the 3rd element of the row is in the first column of B and the 2nd element in the row is in the 2nd column of B.
Easy with some ismember and logical indexing:
A2inB2 = ismember(A(:,2),B(:,2));
A1inB3 = ismember(A(:,1),B(:,3));
c = A( A2inB2 & A1inB3, :);

Related

how can one obtain all combinations of a vector?

I want to find all possible variations (combinations) of a vector, choosing various numbers of elements from that vector.
For example, suppose I have the vector:
x = [1 2 3 4 5];
I can determine the number of combinations for each number of chosen elements:
x = [1 2 3 4 5]';
n = numel(x);
for k = 1:n
combs(k) = nchoosek(n,k);
end
sum(combs)
This results in:
combs = 5 10 10 5 1
sum(combs) = 31
I want a way to store all 31 of these combinations in an array, for example a cell array, with n cells, within each is an array in which each row is a vector combination of the elements.
e.g. at k = 4:
combs{4} =
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
Is there an existing function that does this, or what would be the most simple approach to this?
Call nchoosek with a vector as first input, using arrayfun (or equivalently for) to loop over the number of picked elements:
n = 5;
combs = arrayfun(#(k) nchoosek(1:n,k), 1:n, 'UniformOutput', false);
Here is an approach using dec2bin , find and accumarray:
x = [1 2 3 4 5];
[a b] = find(dec2bin(1:2^numel(x)-1)=='1');
combs = accumarray(a,x(b),[],#(c){c});

How to compare rows (one row to the other row) of two different matrices?

I want to compare rows of two different matrices and find out which rows match.
For example: A= [1 2 3; 4 5 6; 7 8 9; 1 2 3];
B= [1 2 3; 4 5 8; 7 8 9; 7 7 7]
Then I want to compare the first row of A with the first row of B, the second row of A with the second row of B etc. If they do not match, it should return a logical 0 or false and vice versa. Say, if C is the output column vector then,
C = [ 1; 0; 1; 0]
Is there any MatLAB function like ismember. The problem with ismember is that it does not compare row wise but compares if a row in A exist in B.
N=size(A,1);
C=zeros(N,1);
for k=1:N
C(k)=isequal(A(k,:),B(k,:));
end
Without the loop (credits to excaza) :
C=all(A==B,2);

How to use find function for different value at each row of a matrix?

suppose I have values need_find = [1 3 4] and a matrix A in the size of 3xK. I want to find the values of need_find on its corresponding row of A. How can I apply vectorized solution in matlab instead of iterate over each row?
For detailed example as expected;
A = [1 3 4; 1 3 5; 3 4 5];
my_method_do_what_I_want(A,need_find);
The method returns
ans = [1;2;2]
% so I find the index of each element of need_find at corresponding row at A
Long story short :seach 1 at row 1, search 3 at row2, search 4 at row3
Here's one way:
A = [1 3 4; 1 3 5; 3 4 5];
need_find = [1 3 4]
[~,idx] = find(bsxfun(#eq,A,need_find(:)))
which returns
idx =
1
2
2
This simple one-liner won't work if you have repeated values in the rows of A or if there are no matches at all, but I can only go by your example...

average 3rd column when 1st and 2nd column have same numbers

just lets make it simple, assume that I have a 10x3 matrix in matlab. The numbers in the first two columns in each row represent the x and y (position) and the number in 3rd columns show the corresponding value. For instance, [1 4 12] shows that the value of function in x=1 and y=4 is equal to 12. I also have same x, and y in different rows, and I want to average the values with same x,y. and replace all of them with averaged one.
For example :
A = [1 4 12
1 4 14
1 4 10
1 5 5
1 5 7];
I want to have
B = [1 4 12
1 5 6]
I really appreciate your help
Thanks
Ali
Like this?
A = [1 4 12;1 4 14;1 4 10; 1 5 5;1 5 7];
[x,y] = consolidator(A(:,1:2),A(:,3),#mean);
B = [x,y]
B =
1 4 12
1 5 6
Consolidator is on the File Exchange.
Using built-in functions:
sparsemean = accumarray(A(:,1:2), A(:,3).', [], #mean, 0, true);
[i,j,v] = find(sparsemean);
B = [i.' j.' v.'];
A = [1 4 12;1 4 14;1 4 10; 1 5 5;1 5 7]; %your example data
B = unique(A(:, 1:2), 'rows'); %find the unique xy pairs
C = nan(length(B), 1);
% calculate means
for ii = 1:length(B)
C(ii) = mean(A(A(:, 1) == B(ii, 1) & A(:, 2) == B(ii, 2), 3));
end
C =
12
6
The step inside the for loop uses logical indexing to find the mean of rows that match the current xy pair in the loop.
Use unique to get the unique rows and use the returned indexing array to find the ones that should be averaged and ask accumarray to do the averaging part:
[C,~,J]=unique(A(:,1:2), 'rows');
B=[C, accumarray(J,A(:,3),[],#mean)];
For your example
>> [C,~,J]=unique(A(:,1:2), 'rows')
C =
1 4
1 5
J =
1
1
1
2
2
C contains the unique rows and J shows which rows in the original matrix correspond to the rows in C then
>> accumarray(J,A(:,3),[],#mean)
ans =
12
6
returns the desired averages and
>> B=[C, accumarray(J,A(:,3),[],#mean)]
B =
1 4 12
1 5 6
is the answer.

Generate a vector with elements that contain a fixed number of unique values

Suppose I have a vector
A =
3 5 3 3 2 2 4 2 6
I need to produce a new vector B that will contain all these values from the beggining vector A that will result in a unique number of n elements (suppose n=3, for the purpose of this example). The new vector should be B =
3 5 3 3 2
since up to the fifth element of vector A we have 3 unique values(3,5,2).
Actual vectors are a lot larger, so I would rather need a general solution and preferably by avoiding a loop. Any ideas? Thanks in advance
You can use unique for this problem. However, be sure to use the 'stable' option.
A = [3 5 3 3 2 2 4 2 6];
n = 3;
[x, id] = unique(A,'stable');
B = A(1:id(3))
This results in
B =
3 5 3 3 2
Do the following:
A = [3 5 3 3 2 2 4 2 6];
n = 3;
[b,i] = unique(A,'first');
h = sort(i);
A(1:h(n))