Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016

Summing values with database "group by" functionality

Asked by David on 4 May 2012

Tables in databases can easily be transformed by use of the "Group by" function.

Groups ususally occur on a common lable (such as state) while the data columns can be summed, averaged, counted, etc.

In the past, I've take matrices in matlab and dumped them into SQL tables where I can easily use this functionality.

This can take a long time to write the data andif it can be done in Matlab, before writign teh data, it would save considerable time.

Is there a way to do this in MatLab directly?

0 Comments

David

Products

No products are associated with this question.

4 Answers

Answer by Sean de Wolski on 4 May 2012
doc accumarray

0 Comments

Sean de Wolski
Answer by per isakson on 4 May 2012

In the Statistical toolbox there is a class named Dataset. It has a method grpstats.

    grpstats
    Class: dataset
    Summary statistics by group for dataset arrays

I think that does exactly what you ask for and more.

With plain matlab I'm convinced that data in a cell array, a for loop and some logical indexing will do the job. If you provide a toy example of data someone here will give you a piece of code, which demonstrates the approach.

--- CONT. ---

Study the Statistical toolbox Exampel: "Using Dataset Arrays"

--- CONT. 2012-05-07 ---

@David: This "file" is a mess.

  1. There are seven column headers or is it five?
  2. The first and second data row each contains eight values.
  3. The third data row contains nine values.
  4. Both comma and space are used as list separators

Additional information is needed. How to identify "missing values", etc.. Or is space not a separator but part of text values? You tell me.

4 Comments

per isakson on 4 May 2012

Is this copy&pasted from some text file?

Walter Roberson on 7 May 2012

Looks to me as if comma is used as a decimal grouping in this file.

per isakson on 8 May 2012

@Walter, yes indeed.

per isakson
Answer by Peter Perkins on 7 May 2012

David, your example data has a few problems, notably the percent signs. Without having any details about what you are trying to do (and in particular how you might want to define groups in your data), here is an example of what you might do. This example uses a dataset array, but since you have nothing but numeric data, there's no reason why you could not use grpstats on a matrix.

>> % remove embedded spaces from last column header in file
>> % remove stray space from end of next to last line
>> data = dataset('File','tmp.dat','Delimiter',' ');
>> % remove the percent signs
>> data.ID = uint64(data.ID)/100;
>> data.Loss = str2double(strrep(data.Loss,'%',''))/100;
>> data.EL = str2double(strrep(data.EL,'%',''));
>> data
data = 
    Event    ID         Loss          Rate    EL
    1949     44688717          0       14.2      9e-07     
    3216     34845443    1.6e-07      574.8    4.7e-05     
    6443     33870362   8.65e-06      29301   0.002467     
    3721     31438262   6.04e-06      18995   0.001723     
[snip]
     570     15437760      3e-08       50.7    9.4e-06     
    3860     15242217    2.9e-07      435.2   8.14e-05     
>> data.LossGroup = ...
      ordinal(data.Loss,{'High' 'Low'},[],[0,median(data.Loss),Inf])
data = 
     Event    ID          Loss      Rate   EL         LossGroup
     1949     44688717          0    14.2     9e-07   High     
     3216     34845443    1.6e-07   574.8   4.7e-05   High     
     6443     33870362   8.65e-06   29301  0.002467   Low      
     3721     31438262   6.04e-06   18995  0.001723   Low      
    [snip]
      570     15437760      3e-08    50.7   9.4e-06   High     
     3860     15242217    2.9e-07   435.2  8.14e-05   High     
>> lossGroupMeans = grpstats(data,'LossGroup','mean', ...
                             'DataVars',{'Rate' 'ELRelativeRate'})
lossGroupMeans = 
            LossGroup    GroupCount    mean_Rate    mean_EL
    High    High         16            1837.7       0.00026079         
    Low     Low          17             49862        0.0082853         

1 Comment

per isakson on 7 May 2012

Ok, comma serves as a thousand separator.

Peter Perkins
Answer by per isakson on 8 May 2012

Here is a solution that doesn't require the Statistical toolbox.

Separators:

  1. list separator: space
  2. thousand separator: comma
  3. traling: %

Approach:

  1. read the first line (header) to a separate variable.
  2. read the rest of the file to a string buffer
  3. remove "," and "%" from the string buffer
  4. read the string buffer with textscan
  5. convert the cell array of double vectors to a double array
    [ hdr, M ] = Read_text_file();

The whole numbers in the file have been converted to "flints" (see Floating Points ). The mean of the "rows", for which Event==638, can be calculated with logical indexing.

    mean( M( M(:,1)==638, : ), 1 ) 

With "flint" it is safe to use "==". With floating point numbers one need to allow for rounding errors

    mean( M( abs(M(:,5)-0.0024558) < epsilon, : ), 1 )

where epsilon is some appropriate small number.

--- Attachment ---

    function   [ hdr, M ] = Read_text_file()       
        fid = fopen( 'Read_text_file.txt', 'r' );
        hdr = fgetl( fid );
        str = fread( fid, '*char' );
        sts = fclose( fid );       %#ok<NASGU>
        str( str == ',' ) = [];
        str( str == '%' ) = [];
        cac = textscan( str, '%f%f%f%f%f' );
        M   = [ cac{:} ];        
    end

0 Comments

per isakson

Contact us