Одно из возможных решений:
Label = randi([1 6], [100 1]); %# random Nx1 vector of labels
m = [2 3 1 0 1 2]; %# number of records to sample from each category
LabelIndicatorMatrix = false(size(Label)); %# marks selected records
uniqL = unique(Label); %# unique labels: 1,2,3,4,5,6
for i=1:numel(uniqL)
idx = find(Label == uniqL(i)); %# indices where label==k
ord = randperm(length(idx)); %# random permutation
ord = ord(1:min(m(i),end)); %# pick first m_k
LabelIndicatorMatrix( idx(ord) ) = true; %# mark them as selected
end
Чтобы убедиться, что мы удовлетворяем требованиям, мы проверяем:
>> sum(LabelIndicatorMatrix) == sum(m)
ans =
1
Вот моя попытка векторизованного решения:
Label = randi([1 6], [100 1]); %# random Nx1 vector of labels
m = [2 3 1 0 1 2]; %# number of records to sample from each category
%# some helper functions
firstN = @(V,n) V(1:min(n,end)); %# first n elements from vector
pickN = @(V,n) firstN(V(randperm(length(V))), n); %# pick n elements from vector
%# randomly sample labels, and get indices
idx = bsxfun(@eq, Label, unique(Label)'); %'# idx(:,k) indicates where label==k
[r c] = find(idx); %# row/column indices
idx = arrayfun(@(k) pickN(r(c==k),m(k)), 1:size(idx,2), ...
'UniformOutput',false); %# sample m(k) from labels==k
%# mark selected records
LabelIndicatorMatrix = false(size(Label));
LabelIndicatorMatrix( vertcat(idx{:}) ) = true;
%# check results are correct
assert( sum(LabelIndicatorMatrix)==sum(m) )