So say I have two arrays:
A:14 63 13
38 44 23
11 12 13
38 44 23
B:38 44 23
I am trying to use ismember to return the index of every location where B is found in A. All examples I have found online only list the first or last occurrence of a match, I am trying to have a list indices for all values that match, even repeating ones. Thanks
Use ismember with the 'rows' arugment:
ismember(A, B, 'rows')
which results in a logical array [0 1 0 1] which is often better than an array of indices but if you want the indices specifically then just use find:
find(ismember(A,B,'rows'))
to return [2,4]
Note that this method will still work if B has multiple rows e.g. B = [38 44 23; 11 12 13], it will return [0; 1; 1; 1]
You can use bsxfun for the comarison:
idx = find( all( bsxfun(#eq, A, B), 2 )); %// only where all line matches
Results with
idx =
2
4
You can look into pdist2 if you have A and B as Nx3 sized arrays -
[indA,indB] = ind2sub([size(A,1) size(B,1)],find(pdist2(A,B)==0));
ind = [indA,indB]
Thus, in ind you would have the pairwise indices for the matches with the first column representing the indices for A and the second one for B.
Sample run -
A =
14 63 13
38 44 23
11 12 13
14 63 13
38 44 23
B =
38 44 23
14 63 13
ind =
2 1
5 1
1 2
4 2
This is just an improved version of shai's answer for handling multiple rows of B
idx = find(any(all( bsxfun(#eq, A, permute(B,[3 2 1])), 2 ),3));
Sample Run:
A = [14 63 13;
38 44 23;
11 12 13;
38 44 23];
B = [38 44 23;
11 12 13];
idx = find(any(all( bsxfun(#eq, A, permute(B,[3 2 1])), 2 ),3));
>> idx
idx =
2
3
4
Related
I would like to transform the matrix A into the matrix B without using cells (e.g. mat2cell) in Matlab, where
A=[1 2 3;
4 5 6;
7 8 9;
10 11 12;
13 14 15;
16 17 18;
19 20 21;
22 23 24;
25 26 27];
B=[1 2 3 10 11 12 19 20 21;
4 5 6 13 14 15 22 23 24;
7 8 9 16 17 18 25 26 27];
All you need is some reshape + permute magic -
N = 3; %// Cut after every N rows and this looks like the no. of columns in A
B = reshape(permute(reshape(A,N,size(A,1)/N,[]),[1 3 2]),N,[])
This builds a linear index to rearrange the entries of A and then reshapes into the desired matrix B:
m = 3; %// cut size in rows of A. Assumed to divide size(A,1)
n = size(A,2);
p = size(A,1);
ind = bsxfun(#plus, ...
bsxfun(#plus, (1:m).', (0:n-1)*p), permute((0:p/m-1)*m, [1 3 2]));
B = reshape(A(ind(:)), m, [])
In an algorithm, in each level, I have two corresponding matrices in a way one of them has 4 times more element than the other. like children and parent, but i need to have the corresponding elements. consider the two following indices as an example for a level
1 5 9 13
2 6 10 14 and 1 3
3 7 11 15 2 4
4 8 12 16
so for example, I want to receive the element by the index of 1 from the second matrix when i have each of 1,2,5,6 element indices from the first matrix or 2 when i have 3,4,7,8 or 3 for 9,10,16,14 and so on. how can i do that?
as an another example for another level:
1 9 17 25 33 41 49 57
2 10 18 26 34 42 50 58
3 11 19 27 35 43 51 59 and 1 5 9 13
4 12 20 28 36 44 52 60 2 6 10 14
5 13 21 29 37 45 53 61 3 7 11 15
6 14 22 30 38 46 54 62 4 8 12 16
7 15 23 31 39 47 55 63
8 16 24 32 40 48 56 64
Here is one way of doing that:
% Size of matrix A (8x8)
sizeA = 8;
% Size of matrix B (4x4)
sizeB = 4;
% Index of element on matrix A
idxA = 43;
% That is how you can get the corresponding index on matrix B
[r, c] = ind2sub([sizeA sizeA], idxA);
idxB = sub2ind([sizeB sizeB], ceil(r / 2), ceil(c / 2))
It will give you idxB = 10.
It is possible that reshape could be helpful for you.
Consider
A = [1 5 9 13;
2 6 10 14;
3 7 11 15;
4 8 12 16];
B = reshape(permute(reshape(A, [2 2 2 2]), [2 4 1 3]), [4 4]);
B
1 2 5 6
3 4 7 8
9 10 13 14
11 12 15 16
Now you have a nice mapping of the indices from one level to the next.
B(1,:) corresponds to all the indices that map to element 1 in your second array, etc.
When the matrix gets larger (2n x 2n), the operation becomes
B = reshape(permute(reshape(A, [2 n 2 n]), [2 4 1 3]), [n*n 4]);
If you know the 2D indices for the first matrix, then you just divide each by 2 to get the second pair indices:
r = 3;
c = 2;
% Then A(r,c) corresponds to B(floor(r/2), floor(c/2))
If you DON'T know the indices, but instead have the element value itself, you have to find the 2D index first:
val = 7; % test value
[r c] = find(A==val);
other_val = B(floor(r/2), floor(c/2));
I have the following matrix:
MatrixA =
1 10 50
23 45 76
71 81 91
1 2 3
4 5 6
78 89 91
2 3 4
I would like to run the var function for multiple ranges in each column. More specifically, I would like to calculate var for rows 1 through 3, 2 through 4, 3 through 5, etc. for each column. The output I would like would be:
1281.33 1260.33 430.33
1281.33 1564.33 2216.33
1566.33 2004.33 2496.33
... ... ...
I was thinking the syntax would be something along the lines of:
var(MatrixA([1 2 3]:[3 4 5],:))
but this (obviously) does not work.
I can do this using loops, but I was wondering if there is a solution to this that does not involve loops?
You can get rid of one loop using hankel function to create the ranges:
V = [];
for C = MatrixA,
V = [V, var(hankel(C(1:3),C(3:end))).'];
end
For instance if C contains the first column of MatrixA then
>> hankel(C(1:3),C(3:end))
ans =
1 23 71 1 4
23 71 1 4 78
71 1 4 78 2
and
>> var(hankel(C(1:3),C(3:end)))
ans =
1281.3 1281.3 1566.3 1902.3 1876
You could be a little creative with bsxfun and reshape to compute an index array and then compute the variances:
n = 3;
idx = bsxfun(#plus, 1:size(MatrixA, 1) - n + 1, (0:n - 1)');
B = reshape(var(reshape(MatrixA(idx, :), 3, [])), [], size(MatrixA, 2));
If I have a matrix
F=[ 24 3 17 1;
28 31 19 1;
24 13 25 2;
47 43 39 1;
56 41 39 2];
in the first three columns I have feature values a forth column is for class labels. my problem is to get rid of same feature values when class label is different for that particular values.
like for F matrix I have to remove the rows 1,3,4 and 5 ,because for first column there are 2 different values in column four and same is for third column (39 and 39)as class label again got changed.
so output should look like
F=[28 31 19 1];
The straightforward approach would be iterating over the columns, counting the number of different classes for each value, and removing the rows for values associated to more than one class.
Example
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
%// Iterate over columns
for col = 1:size(F, 2) - 1
%// Count number of different classes for each value
[vals, k, idx] = unique(F(:, col));
count = arrayfun(#(x)length(unique(F(F(:, col) == x, end))), vals);
%// Remove values associated to more than one class
F(count(idx) > 1, :) = [];
end
This results in:
F =
28 31 19 1
Another take at the problem, without arrayfun (edited)
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
Separate both classes:
A1 = F(F(:,4)==1,1:3);
A2 = F(F(:,4)==2,1:3);
Replicate them to a 3D matrix to compare each line of class1 with each line of class2:
B2 = repmat(shiftdim(A2',-1),size(A1,1),1);
B1 = repmat(A1,[1,1,size(A2,1)]);
D4 = squeeze(sum(B1 == B2,2));
remove rows duplicated rows
A1(logical(sum(D4,2)),:) = [];
A2(logical(sum(D4,1)),:) = [];
reconstruct original matrix
R = [A1 ones(size(A1,1),1);A2 2*ones(size(A2,1),1)];
If I have a matrix
F=[ 24 3 17 1;
28 31 19 1;
24 13 25 2;
47 43 39 1;
56 41 39 2];
in the first three columns I have feature values a forth column is for class labels. my problem is to get rid of same feature values when class label is different for that particular values.
like for F matrix I have to remove the rows 1,3,4 and 5 ,because for first column there are 2 different values in column four and same is for third column (39 and 39)as class label again got changed.
so output should look like
F=[28 31 19 1];
The straightforward approach would be iterating over the columns, counting the number of different classes for each value, and removing the rows for values associated to more than one class.
Example
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
%// Iterate over columns
for col = 1:size(F, 2) - 1
%// Count number of different classes for each value
[vals, k, idx] = unique(F(:, col));
count = arrayfun(#(x)length(unique(F(F(:, col) == x, end))), vals);
%// Remove values associated to more than one class
F(count(idx) > 1, :) = [];
end
This results in:
F =
28 31 19 1
Another take at the problem, without arrayfun (edited)
F = [24 3 17 1; 28 31 19 1; 24 13 25 2; 47 43 39 1; 56 41 39 2];
Separate both classes:
A1 = F(F(:,4)==1,1:3);
A2 = F(F(:,4)==2,1:3);
Replicate them to a 3D matrix to compare each line of class1 with each line of class2:
B2 = repmat(shiftdim(A2',-1),size(A1,1),1);
B1 = repmat(A1,[1,1,size(A2,1)]);
D4 = squeeze(sum(B1 == B2,2));
remove rows duplicated rows
A1(logical(sum(D4,2)),:) = [];
A2(logical(sum(D4,1)),:) = [];
reconstruct original matrix
R = [A1 ones(size(A1,1),1);A2 2*ones(size(A2,1),1)];