octave

How to use "cellfun" to get the number of occurrences of the mode


I would like to do a calculation in each cell of a cell array in Octave: 1) get the number of occurrences of the mode in each cell, and 2) divide this value by the length of the array in each cell. e.g., A=1×2 cell array {[1 2 3 1 1]} {[1 1 1 1]};

the number of occurrences of the mode is 3 and 4,divided by the length of the array in each cell 5 and 4, it should be calculated as 3/5 4/4 in the cells, respectively.

If I use cellfun like this m=cellfun(@(x) mode(x)./length(x),A);

the part of the function "mode(x)" return the mode of the array rather than the number of occurrence, because the number of occurrence can only be got by [m, f, c] = mode (A)

where f is the number of occurrence of the mode.

How can I return f in cellfun to do the calculation? Thank you


Solution

  • what version of Octave are you using?

    Testing with version 9.1.0, the mode function does have a form where it returns the number of instances of the mode:

    >> help mode
    
    -- M = mode (X)
     -- M = mode (X, DIM)
     -- [M, F, C] = mode (...)
    ...
        The return variable F is the number of occurrences of the mode in
         the dataset.
    
    >> [a,b,c] = mode([1 2 3 1 1])
    a = 1
    b = 3
    c =
    {
      [1,1] = 1
    }
    

    now, because it's the second return variable, it would be troublesome to make a one-line anonymous function to get it. If that's not a requirement, you can do:

    A =  {[1 2 3 1 1]; [1 1 1 1]}
    A =
    {
      [1,1] =
    
         1   2   3   1   1
    
      [2,1] =
    
         1   1   1   1
    
    }
    
    >> [~,f,~] = cellfun (@mode, A)  ## ~ tells Octave to ignore that output.
    f =
    
       3
       4
    
    >> L = cellfun (@length, A)
    L =
    
       5
       4
    
    >> m = f./L
    m =
    
       0.6000
       1.0000
    

    If you really want a one-line anonymous function, we can note that the mode elements locations can be found with find, and then numel will give us the incidence count. so the [~,f,~] output can be replaced by something like:

    >> f = cellfun(@(x) numel(find(x==mode(x))), A)
    f =
    
       3
       4
    

    so that can be combined with numel to make:

    >> m = cellfun(@(x) numel(find(x==mode(x)))/numel(x), A)
    m =
    
       0.6000
       1.0000
    

    Normally anonymous functions in Octave introduce a significant slowdown, but so does calling cellfun. A quick timing test shows that the 1-line anonymous function is only bit slower than the direct function calls with two calls to cellfun:

    tic; for idx = 1:100, m = cellfun(@(x) numel(find(x==mode(x)))/numel(x), A);endfor, toc
    Elapsed time is 0.250258 seconds.
    
    >> tic; for idx = 1:1000, [~,f,~] = cellfun (@mode, A); L = cellfun(@numel, A);m = f./L; endfor, toc
    Elapsed time is 0.236082 seconds.
    

    (numbers above chosen as consistent values from multiple tests.)