Find row indices of different values ββin a matrix
Having matrix A (n * 2) as source and B as a vector containing a subset of the elements of A, I would like to find the row index of the elements.
A=[1 2;1 3; 4 5];
B=[1 5];
F=arrayfun(@(x)(find(B(x)==A)),1:numel(B),'UniformOutput',false)
gives the following outputs in a cell according to this help page
[2x1 double] [6]
specifying the indices of all cases in the column. But I would like to have row indices. those. I would like to know that item 1 happens on line 1 and line 2, and item 5 only happens on line 3. If the indices were across a number of rows, I could use ceil (F {x} / 2) to get the desired result. Now with a variable number of lines, what's your suggested solution? As it may be that there is no complete "rows" include tag in the ismember function, it does not work. Also, I would like to know all the indices of the specified items. Thanks in advance for any help.
source to share
Approach 1
To convert F
from the current linear-index form to index strings use mod
:
rows = cellfun(@(x) mod(x-1,size(A,1))+1, F, 'UniformOutput', false);
You can combine this with your code in one line. Also note that you can directly use B
as input arrayfun
and you will avoid one step of indexing:
rows = arrayfun(@(x) mod(find(x==A)-1,size(A,1))+1, B(:), 'UniformOutput', false);
How it works :
F
as indicated by your code is a linear index in the form of a column. This means that the index runs through the first column B
, starts at the top of the second column and goes down again, etc. Thus, the line number can only be obtained using the modulo ( mod
) operation .
Approach 2
Using bsxfun
and accumarray
:
t = any(bsxfun(@eq, B(:), reshape(A, 1, size(A,1), size(A,2))), 3); %// occurrence pattern
[ii, jj] = find(t); %// ii indicates an element of B, and jj is row of A where it occurs
rows = accumarray(ii, jj, [], @(x) {x}); %// group results according to ii
How it works :
Assuming A
and B
as in your example t
is a 2x3 matrix
t =
1 1 0
0 0 1
mth row t
contains 1
n in column if mth element from B
occurs in nth row B
. These values ββare converted to row and column form with find
:
ii = 1 1 2 jj = 1 2 3
This means that the first item B
appears on lines 1 and 2 of A
; and the second is on line 3 B
.
Finally, the values jj
are grouped (c accumarray
) according to their respective value ii
to generate the desired result.
source to share
One approach with bsxfun
and accumarray
-
%// Create a match of B in A with each column of matches representing the
%// rows in A where there is at least one match for each element in B
matches = squeeze(any(bsxfun(@eq,A,permute(B(:),[3 2 1])),2))
%// Get the indices values and the corresponding IDs of B
[indices,B_id] = find(matches)
%// Or directly for performance:
%// [indices,B_id] = find(any(bsxfun(@eq,A,permute(B(:),[3 2 1])),2))
%// Accumulate the indices values using B_id as subscripts
out = accumarray(B_id(:),indices(:),[],@(x) {x})
Example run -
>> A
A =
1 2
1 3
4 5
>> B
B =
1 5
>> celldisp(out) %// To display the output, out
out{1} =
1
2
out{2} =
3
source to share