Search code examples
matlabmachine-learningstructuresignal-processingcell-array

Saving, extracting relevant data from cell arrays in multiple loops in MATLAB


sorry for asking may be this is simple question but I am stuck in it. It’s related to cell arrays.

I have delay, offset, and threshold.

 delay = [0.01:0.01:0.03];
 offset = [0.02:0.01:0.04];
 threshold = [0.4:0.1:0.9];       
 limit_for_idx  = [0.4:0.1:0.9]; 
 limit = [0.4:0.1:0.9];

I have tried to provide an example to ask only a part where I have some issue.

In first part of loop I have received complete values for Delay, Offset, J, r, threshold as shown in figure for all loops.

delay =0.0300 offset=0.0400 J=16 25 24 25 r = 24 21 46 18 threshold = 0.4:0.9

enter image description here

Then I filtered Minimum value of J and maximum value of r and threshold values which corresponds to min J and max r. I have received these values as shown in figure.

   [min_J,min_J_loc] = min(J(:))
   [max_r,max_r_loc] = max(r(:))
   thresh_min_J = threshold(min_J_loc);
   thresh_max_r = threshold(max_r_loc);

enter image description here

For the one case I have marked with red but I will receive these combinations for all loops like shown in whole picture.

Questions:

• I want to find the combination of delay, offset, threshold which contains minimum J and maximum r as shown in figure from all the combinations I need I need the combination of delay ,offset, threshold which contain minimum J and maximum r . I have saved values in the cell array as I am confused that how to get the combination out of cell array.

• Is there any good approach to save the values or may be structures if yes can someone explain how just small hint will also work.

Code :

 delay = [0.01:0.01:0.03];
 offset = [0.02:0.01:0.04];
 threshold = [0.4:0.1:0.9];       
 limit_for_idx  = [0.4:0.1:0.9]; 
 limit = [0.4:0.1:0.9];         


 J=0;
 T = 1;
 b=1;
 K=1;
 for H = 1:numel(delay)
     for G = 1:numel(offset)
        for R = 1:numel(threshold);  

          J = randi([10 25],1,4);    
           r = randi([10 50],1,4);
        end
   [min_J,min_J_loc] = min(J(:))
   [max_r,max_r_loc] = max(r(:))
   thresh_min_J = threshold(min_J_loc);
   thresh_max_r = threshold(max_r_loc);
       out{K,:} = [ delay(H) offset(G)  J  r threshold];
       output{T,:} = [delay(H) offset(G)  min_J  max_r  thresh_min_J  thresh_max_r];
     K=K+1;
     T = T+1;
     end

 end


  for X = 1:numel(out)
      disp(' delay ,   offset(G) ,  J,   r ,  threshold  ') 
      Q = out{X};
      disp(Q)
  end

   for X = 1:numel(output)
        disp(' delay ,   offset(G) ,  min_J,   max_r ,   thresh_min_J  thresh_max_r ')
      Z =  output{X};
      disp(Z)

   end 

Solution

  • Check out this modified version of your example:

    function varargout = q47452082
    delay = (0.01:0.01:0.03);
    offset = (0.02:0.01:0.04);
    threshold = (0.4:0.1:0.9);
    nD = numel(delay);
    nO = numel(offset);
    J = randi([10 25],1,4,nD,nO);
    r = randi([10 50],1,4,nD,nO);
    %% Preallocate
    %{
    The simplest way to do it:
    out    = NaN(nD*nO,3*1+2*4);
    output = NaN(nD*nO,6);
    %}
    out = struct('delay',[],'offset',[],'J',[],'r',[],'threshold',[]);
    out = repmat(out,nD*nO,1);
    output = struct('delay',[],'offset',[],'min_J',[],'max_r',[],...
      'thresh_min_J',[],'thresh_max_r',[]);
    output = repmat(output,nD*nO,1);
    fn{2} = fieldnames(output);
    fn{1} = fieldnames(out);
    %% Populate the data structures:
    K = 1;
    for H = 1:numel(delay)
      for G = 1:numel(offset)
        [min_J,min_J_loc] = min(J(:,:,H,G));
        [max_r,max_r_loc] = max(r(:,:,H,G));
        thresh_min_J = threshold(min_J_loc);
        thresh_max_r = threshold(max_r_loc);
        data = {delay(H),offset(G),J(:,:,H,G),r(:,:,H,G),threshold};
        for indF = 1:numel(fn{1})
          out(K).(fn{1}{indF}) = data{indF};
        end
        data = {delay(H), offset(G), min_J, max_r, thresh_min_J, thresh_max_r};
        for indF = 1:numel(fn{2})
          output(K).(fn{2}{indF}) = data{indF};
        end
        K = K+1;
      end
    end
    
    if nargout == 0 % if no outputs requested, print
      if ~verLessThan('matlab','8.2') % tables exist in MATLAB R2013b or newer
        disp(struct2table(out));
        disp(struct2table(output));
      else
        for X = 1:numel(out)
          Q = out(X);
          disp(Q)
        end
        for X = 1:numel(output)
          Z = output(X);
          disp(Z)
        end
      end
    else % otherwise output the desired data:
      % OPTION #1: separate variables
      % You should call the function like so: [min_J_cases,max_r_cases] = q47452082();
      varargout{1} = output([output.min_J] == min([output.min_J]));
      varargout{2} = output([output.max_r] == max([output.max_r]));
      % OPTION #2: 1 output, 2x1 cell
      %{
      varargout = {output([output.min_J] == min([output.min_J]));...
                   output([output.max_r] == max([output.max_r]))};
      %}
      % OPTION #3: 1 output, 2x1 struct
      %{
      varargout = {[output([output.min_J] == min([output.min_J]));...
                    output([output.max_r] == max([output.max_r]))]};
      %}
    end
    

    Several things you should note:

    • I removed some unused variables.
    • I preallocated out and output as struct arrays.
    • I removed the loop around the J,r randomization (since it does nothing) and moved the random number generation to before the loop (no reason to do it in every iteration when it can be done all at once at the beginning).
    • I perform assignment using dynamic field references to both struct arrays.
    • I added a demonstration of how to run different code depending on different MATLAB version (and hence, different supported functionality) - see printing at the end.
    • The function only prints things if you don't request outputs.
    • There is likely room for further vectorization of your code (i.e. getting rid of loops).