Search code examples
arraysmatlabcellcell-array

Classify data (cell array) based on years in MATLAB


Suppose that we have this cell array of data :

a={43 432 2006;
254 12 2008;
65 35 2000;
64 34 2000;
23 23 2006;
64 2 2010;
32 5 2006;
22 2 2010}

Last column of this cell array is years. I want classify data(rows) based on years like this :

a_2006 = {43 432 2006;
32 5 2006;
32 5 2006}

a_2008 = {254 12 2008};

a_2000 = {65 35 2000;
64 34 2000}

a_2010 = {64 2 2010;
22 2 2010}

I have different years in column three in every cell array (this cell array is a sample) so I want an automatic method to determine the years and classify them to a_yearA , a_yearB etc. or other naming that I can distinguish years and call data with years easily in following codes.

How can I do this?

Thanks.da


Solution

  • eval is not recommanded here. I would suggest to save it in a struct array like that

    a={43 432 2006;
    254 12 2008;
    65 35 2000;
    64 34 2000;
    23 23 2006;
    64 2 2010;
    32 5 2006;
    22 2 2010};
    
    tmp = cell2mat(a);
    % clear a or take another variable name for your struct to prevent warnings
    clear a 
    years=unique(tmp(:,3));
    for n = 1:numel(years)
        a.(['a_' num2str(years(n))])=tmp(tmp(:,3)==years(n),:);
    end
    

    looks like that

    >> a
    
    a = 
    
        a_2000: [2x3 double]
        a_2006: [3x3 double]
        a_2008: [254 12 2008]
        a_2010: [2x3 double]
    
    >> a.a_2000
    
    ans =
    
              65          35        2000
              64          34        2000
    

    Furthermore, you can easily access your struct arrays in a loop again (what you can't do such easy with the eval hack).

    >> names=fieldnames(a)
    
    names = 
    
        'a_2000'
        'a_2006'
        'a_2008'
        'a_2010'
    
    >> for n = 1:numel(names)
        a.(names{n})
    end
    

    update with strings in cell

    Well, say there are strings in your cell

    a={'43' '432' 2006;
    '254' '12' 2008;
    '65' '35' 2000;
    '64' '34' 2000;
    '23' '23' 2006;
    '64' '2' 2010;
    '32' '5' 2006;
    '22' '2' 2010};
    
    % save original variable 'a' for accessing later
    tmp.cell = a;
    
    % save just the years in a matrix for more easy accessing + we need the
    % indizes for getting the values from the cell later in the loop
    tmp.years = cell2mat(a(:,3));
    
    % clear variable a or take another variable name for your struct to prevent warnings
    clear a 
    
    % get unique years for iteration
    tmp.unique_years=unique(tmp.years);
    
    for n = 1:numel(tmp.unique_years)
        a.(['a_' num2str(tmp.unique_years(n))])=tmp.cell(tmp.years==tmp.unique_years(n),:);
    end
    

    The result is the same, but your structs are now cells

    >> a
    
    a = 
    
        a_2000: {2x3 cell}
        a_2006: {3x3 cell}
        a_2008: {'254'  '12'  [2008]}
        a_2010: {2x3 cell}