Search code examples
matlabgroupingaveragecell-array

Averaging a row of a cell array dependent on a string in another row


I've got this cell-array:

times = {'plot'      'plot'      'plot'      'plot'      'plot'      'hist'      'plot'      'plot'      'plot'      'plot'  ;
         [0.0042]    [0.0026]    [0.0032]    [0.0054]    [0.0049]    [0.0106]    [0.0038]    [0.0026]    [0.0030]    [0.0026]}

now I want to create an average for each type in the first row and save it to an new cell like this:

result = {'hist'      'plot'  ;  
          [0.0106]    [0.0036];
          [     1]    [     9]}

The first row are the types, the second row are the averages and the third row are the number of elements.

I solved my problem with this code:

labels = unique(times(1,:));
result = cell(3,numel(labels));

for i = 1 : numel(labels)
    result(1,i) = labels(i);
    times2avg = cell2mat(times(2,strcmp(times(1,:), labels(i))));
    result{2,i} = mean(times2avg);
    result{3,i} = numel(times2avg);
end

My question now is whether there is an easier or more ideal solution to my problem.


Solution

  • With a combination of unique and accumarray you can achieve what you want.

    %// example data
    times = { 'plot' 'plot' 'plot' 'plot' 'hist' 'plot'; 
                [1]    [2]    [3]   [4]    [5]    [6] }
    %// extract data
    data = [times{2,:}]
    
    %// get types and their locations
    [types, ~, subs] = unique(times(1,:))
    
    %// calculate average values
    avgs = accumarray(subs(:),data(:),[],@mean)
    
    %// count occurences
    nums = accumarray(subs(:),data(:),[],@numel)
    
    %// gather everything for output
    result = [types; num2cell(avgs.'); num2cell(nums.')]
    

    result = 
    
        'hist'    'plot'  
        [   5]    [3.2000]
        [   1]    [     5]