Slicing 2D array based on conditions specified in a seperate list
7 views (last 30 days)
Show older comments
I have 2D (NxM) matrix with N rows and M columns (the dimensions depend on experimental data I collect, for example see matrix A below:
A = [1 0 0 1 0; 0 1 0 1 0 ; 1 0 0 1 1; 0 0 0 1 1]
Information about the identity of each row is specified by another Nx1 column vector, for example see matrix L below.
L = [A1 C4 F7 E5]*
So, row 1 of matrix A belongs to group "A1", row 2 belongs to group "C4" and so on.
I would like to create a slice of matrix A that contains specific rows that I specify from vector L.The grouping terms depend on experimental data, but I would like the ability to generate a series of slices based on specific elements of vector L that I define.
For example, I would like slice of matrix A containing only groups "A1" and "F7" from vector L to form the in a new 2xM matrix S. :
S = [1 0 0 1 0; 1 0 0 1 1]
I would appreciate some advice on how to do generic slicing of matrix A by using a subset of group identifiers from vector L. Any feedback would be much appreciated.
0 Comments
Accepted Answer
John BG
on 3 Feb 2017
Hi Sharf
1.
Input matrices
A = [1 0 0 1 0; 0 1 0 1 0 ; 1 0 0 1 1; 0 0 0 1 1]
L = ['A1' ;'C4'; 'F7'; 'E5']
2.
decide where to slice with for instance vector called query
query=[C4]
or
query='C4'
3.
thin slice, just one layer
A(find(sum(bsxfun(@eq,L,query),2)==2),:)
4.
a thicker slice, for instance
query=['A1';'F7';'A1']
now
[sz1 sz2]=size(query)
D=[];
for k=1:1:sz1
D=[D;find(sum(bsxfun(@eq,L,query(k,:)),2)==2)];
end
D contains the amount of occurrences
D =
1
3
1
.
since in your question it's not mentioned whether you want the resulting matrix to take into account repetitions or not, I am showing you both
5.
taking into account repetitions
A(D,:)
=
1 0 0 1 0
1 0 0 1 1
1 0 0 1 0
6.
considering repeated request for same row but ordering them with sort
A(sort(D),:)
=
1 0 0 1 0
1 0 0 1 0
1 0 0 1 1
7.
without taking into account repeated query for same row:
A(unique(D),:)
=
1 0 0 1 0
1 0 0 1 1
with best hope of having helped solve your question,
if you find this answer useful would you please be so kind to mark my answer as Accepted Answer?
To any other reader, please if you find this answer of any help solving your question,
please click on the thumbs-up vote link,
thanks in advance
John BG
1 Comment
Jan
on 3 Feb 2017
Edited: Jan
on 3 Feb 2017
This line:
A(find(sum(bsxfun(@eq,L,query),2)==2),:)
displays the MLint warning concerning the unnecessary find. You can simply omit it to use the faster logical indexing.
The lines:
D=[];
for k=1:1:sz1
D=[D;find(sum(bsxfun(@eq,L,query(k,:)),2)==2)];
end
let grow the output D in each iteration. This wastes resources and a "pre-allocation" (search for this term in the forum) is recommended:
D = zeros(1,sz1);
for k = 1:sz1
D(k) = find(sum(bsxfun(@eq,L,query(k,:)),2)==2);
end
More Answers (1)
Jan
on 3 Feb 2017
Edited: Jan
on 7 Feb 2017
Keys = {'A1', 'C4', 'F7', 'E5'};
Data = [1 0 0 1 0; 0 1 0 1 0 ; 1 0 0 1 1; 0 0 0 1 1];
WantedKeys = {'A1', 'F7'};
[found, index] = ismember(WantedKey, Keys);
WantedData = Data(index, :)
[EDITED] Taken from Stephen Coboldick's comment: If the Keys are not unique, the order of the arguments for ismember are changed:
Keys = {'A1', 'C4', 'F7', 'A1'};
WantedKeys = {'A1', 'F7'};
Data = [1 0 0 1 0; 0 1 0 1 0 ; 1 0 0 1 1; 0 0 0 1 1];
index = ismember(Keys, WantedKeys);
Result = Data(index, :)
ans =
1 0 0 1 0
1 0 0 1 1
0 0 0 1 1
3 Comments
Stephen23
on 3 Feb 2017
Edited: Stephen23
on 6 Feb 2017
>> Keys = {'A1', 'C4', 'F7', 'A1'};
>> WantedKeys = {'A1', 'F7'};
>> Data = [1 0 0 1 0; 0 1 0 1 0 ; 1 0 0 1 1; 0 0 0 1 1];
>> index = ismember(Keys,WantedKeys);
>> Data(index,:)
ans =
1 0 0 1 0
1 0 0 1 1
0 0 0 1 1
@Tal Sharf: note that Jan Simon's solution is a much better concept than doing this in a loop.
See Also
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!