2

I have a cell array in MATLAB as follow, the first column is a list of user ID:

A = { 'U2', 'T13', 'A52';  
      'U2', 'T15', 'A52';  
      'U2', 'T18', 'A52';  
      'U2', 'T17', 'A995'; 
      'U4', 'T18', 'A53';  
      'U4', 'T13', 'A64';  
      'U4', 'T18', 'A64';
      ....
     }

I also have a cell array B contains the unique ID for user as follow:

B = {'U2', 'U4'}

My goal is try to randomly select two samples for each user. Assume each user at least have two samples in B.

One example is the C as follow:

C = { 'U2', 'T13', 'A52';  
      'U2', 'T18', 'A52';   
      'U4', 'T13', 'A64';  
      'U4', 'T18', 'A64';
        ...
     }

How to generate those sample?

1
  • I use very complicate ways. use three nested for loops. Any faster way? Commented Apr 7, 2018 at 15:23

3 Answers 3

2

The following code should produce what you are looking for:

A = {
  'U2', 'T13', 'A52';  
  'U2', 'T15', 'A52';  
  'U2', 'T18', 'A52';  
  'U2', 'T17', 'A995'; 
  'U4', 'T18', 'A53';  
  'U4', 'T13', 'A64';  
  'U4', 'T18', 'A64';
  'U7', 'T14', 'A44';  
  'U7', 'T14', 'A27';  
  'U7', 'T18', 'A27';  
  'U7', 'T13', 'A341';  
  'U7', 'T11', 'A111';
  'U8', 'T17', 'A39';  
  'U8', 'T15', 'A58'
};

% Find the unique user identifiers...
B = unique(A(:,1));
B_len = numel(B);

% Preallocate a cell array to store the results...
R = cell(B_len*2,size(A,2));
R_off = 1;

% Iterate over the unique user identifiers...
for i = 1:B_len

    % Pick all the entries of A belonging to the current user identifier...
    D = A(ismember(A(:,1),B(i)),:);

    % Pick two random non-repeating entries and add them to the results...
    idx = datasample(1:size(D,1),2,'Replace',false);
    R([R_off (R_off+1)],:) = D(idx,:); 

    % Properly increase the offset to the results array...
    R_off = R_off + 2;

end

Here is one of the possible outcomes for the code snippet above:

>> disp(R)

    'U2'    'T13'    'A52' 
    'U2'    'T18'    'A52' 
    'U4'    'T13'    'A64' 
    'U4'    'T18'    'A64' 
    'U7'    'T14'    'A44' 
    'U7'    'T13'    'A341'
    'U8'    'T17'    'A39' 
    'U8'    'T15'    'A58' 

For more information about the functions I used, refer to the following pages of the official Matlab documentation:

Sign up to request clarification or add additional context in comments.

Comments

1
A = { 'U2', 'T13', 'A52';  
      'U2', 'T15', 'A52';  
      'U2', 'T18', 'A52';  
      'U2', 'T17', 'A995'; 
      'U4', 'T18', 'A53';  
      'U4', 'T13', 'A64';  
      'U4', 'T18', 'A64'
     };
B = {'U2', 'U4'};


userRep = [];
 for i = 1:size(A,1)
     for j = 1:size(B,2)
        if A{i,1} == B{j}
            userRep(end+1,:) = [j,i];
        end
     end
 end


 numberOfSamp = 2;
 samples = {};
 for i = 1:size(B,2)
     cellPos = userRep(userRep(:,1) == i,:);
     cellPos = cellPos(randi([1 size(cellPos,1)],[min(numberOfSamp,size(cellPos,1)),1]),:);
     for j = 1:size(cellPos,1)
        samples{end+1,1} = A{cellPos(j,2),1};
        samples{end,2} = A{cellPos(j,2),2};
        samples{end,3} = A{cellPos(j,2),3};
     end
end

samples

1 Comment

If you use loops you should preallocate whenever possible
1

Let the input variables be defined as

A = { 'U2', 'T13', 'A52';  
      'U2', 'T15', 'A52';  
      'U2', 'T18', 'A52';  
      'U2', 'T17', 'A995'; 
      'U4', 'T18', 'A53';  
      'U4', 'T13', 'A64';  
      'U4', 'T18', 'A64';
     };                     % data
B = {'U2', 'U4'};           % unique identifiers
n = 2;                      % number of results per group

You can achieve what you want as follows:

  1. Create a grouping variable, so each ID corresponds to an integer;
  2. Pick n random values from the set of row indices corresponding to each group;
  3. Use the set of all such indices to index into A.

Code:

[~, m] = ismember(A(:,1), B);                                  % step 1
s = accumarray(m, 1:size(A,1).', [], @(x){randsample(x, n)});  % step 2
C = A(vertcat(s{:}),:);                                        % step 3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.