Reputation: 195
I have three vectors A, B and C of same size. A and B are numeric quantities while C is a cell array of strings. I want to generate sub-vectors of A based on the unique values of B and C. For example, let
A = [0.45 0.89 0.12 0.35 0.40 0.93 0.12 0.35 0.72 0.59];
B = [1 1 3 1 8 1 8 8 1 1];
C = [{'Tom'}, {'Mary'}, {'Dick'}, {'Harry'}, {'Dick'}, {'Tom'}, {'Tom'}, {'Mary'}, {'Tom'}, {'Mary'}];
So, I first tried to find the unique values of B and C using MATLAB's unique function. The results are as follows:
unique(B)
ans =
1 3 8
unique(C)
ans =
'Dick' 'Harry' 'Mary' 'Tom'
Now, I want to arrange the vector A by the unique values in B and C. Suppose the indices of the unique values of the first element of unique(B) are [row_b1, colb1], second element indices be [row_b2, colb2] and so on. Then, based on the unique values in B, I would like to generate the following three vectors:
A_B1 = A(rowb1, colb1);
A_B2 = A(rowb2, colb2);
A_B3 = A(rowb3, colb3);
Similarly, based on the unique values of C, I would like to generate following vectors:
A_C1 = A(rowc1, colc1);
A_C2 = A(rowc2, colc2);
A_C3 = A(rowc3, colc3);
A_C4 = A(rowc4, colc4);
However, I didn't find anything in the unique command that tells me the indices of the unique values in the vector i.e. row_b1, col_b1, ... etc. Could someone please point out how to obtain these indices? Any help will be greatly appreciated.
Edit1: I should mention that I posted a general case. But in my problem A, B and C are matrices. I figured if I could solve this for a vector, then it should be a similar extension for a matrix.
Edit2: Here are the answers I am expecting:
A_B1 = [0.45 0.89 0.35 0.93 0.72 0.59]
A_B2 = [0.12]
A_B3 = [0.40 0.12 0.35]
and
A_C1 = [0.45 0.93 0.12 0.72]
A_C2 = [0.89 0.35 0.59]
A_C3 = [0.12 0.40]
A_C4 = [0.35]
Upvotes: 2
Views: 236
Reputation: 1881
You can use the extra outputs of the unique function in your favor:
[ub ib jb]=unique(B);
Where ub,ib and jb are defined as:
Which you can use to get your A_B values:
A_B=A(ib);
The same logic applies to C:
[cu ic jc]=unique(C);
A_C=A(ic);
Since A, B and C are vectors of the same size.
EDIT
Since (rowb1,colb1), (rowb2,colb2) and (rowb3,colb3) are just placeholders as explained in the comments, what you really want is the indexes where each unique value appears and use these indexes to get your A values. To get the position where each unique value appears you can use:
>> idxA_B=bsxfun(@eq,B,unique(B)')
ans =
1 1 0 1 0 1 0 0 1 1
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 1 1 0 0
So your A_B values are given by:
A_B1=A(idxA_B(1,:));
A_B2=A(idxA_B(2,:));
A_B3=A(idxA_B(3,:));
The same logic applies to C. But as @Parag S. Chandakkar pointed out, @eq does not work with strings so you need to get your C indexes the following way:
aux=cellfun(@(x) strcmp(x,unique(C)'),C,'UniformOutput',false);
idxA_C = [aux{:}];
A_C1=A(idxA_C(1,:));
A_C2=A(idxA_C(2,:));
A_C3=A(idxA_C(3,:));
A_C4=A(idxA_C(4,:));
Upvotes: 1
Reputation: 9075
Lets consider the same example.
A = [0.45 0.89 0.12 0.35 0.40 0.93 0.12 0.35 0.72 0.59];
B = [1 1 3 1 8 1 8 8 1 1];
C = [{'Tom'}, {'Mary'}, {'Dick'}, {'Harry'}, {'Dick'}, {'Tom'}, {'Tom'}, {'Mary'}, {'Tom'}, {'Mary'}];
[uniqueB,indB,~]=unique(B);
[uniqueC,indC,~]=unique(C);
A_indB=A(indB); //This and the following line is what you want, I think.
A_indC=A(indC);
This is given in the documentation for unique
.
This is how I would do it for matrices (numeric as well as character).
First generate some matrices.
A1=[A;A(randperm(length(A)));A(randperm(length(A)))];
B1=[B;B(randperm(length(B)));B(randperm(length(B)))];
C1=[C;C(randperm(length(C)));C(randperm(length(C)))];
Now,
indB=arrayfun(@(x) bsxfun(@eq,B1,x),unique(B1),'uni',0);
indC=arrayfun(@(x) strcmp(C1,x),unique(C1),'uni',0); % above line only works
% for numeric arrays
and get the answer as,
A_B1=A(indB{1,1});
A_B2=A(indB{2,1});
A_C1=A(indC{1,1});
A_C2=A(indC{2,1}); % and so on
Upvotes: 1