Home > atmlab > math > binned_statistics.m

binned_statistics

PURPOSE ^

% BINNED_STATISTICS Calculate statistics for a cell array of binned data.

SYNOPSIS ^

function out = binned_statistics(data_bins, statistics, filter, replace, opt)

DESCRIPTION ^

% BINNED_STATISTICS Calculate statistics for a cell array of binned data.

 This functions calculates statistics for binned data. data_bins has to
 be a cell array where each cell contains an array of values.
 Each function given in the statistics parameter is called for each
 cell of data_bins. Optionally, a filter function can be passed which is
 applied to the binned data.

 FORMAT   out = binned_statistics(data_bins, statistics, filter, replace, opt)

 OUT   out          Structure containing the results for each applied
                    statistics function.
 IN    data_bins    Cell of gridded vectors of data.
       statistics   Cell array of statistic function references.
       filter       Function to filter the binned data.  Function is
                    expected to return a subset of the original data, i.e.
                    @(X)X(X>0).  May also be cell thereof with multiple.
       replace      replace empty cells with <replace> (optional argument).
                         "replace" may also be a cell with as many elements as there are function
                         handles that you plan to use,
                         e.g., replace = {[0 0 0],NaN,-9} for 3 suitable
                         function handles. If "replace" is not a cell, the same
                         entry will be used for each function handle
 OPT         structure of extra options:
       opt.dataClass = 'class' (e.g., 'single'); This ensures
                   that all the data in the cell is your class of choosing

 EXAMPLES
 * Calculate number of elements per bin, mean value for each bin:
   out = binned_statistics(data_bins, {@numel, @mean});

 * Calculate mean and standard deviation, ignore all elements smaller
   than zero by passing the filter criteria as an anonymous function:
   out = binned_statistics(data_bins, {@mean, @std}, @(x)(x(x>=0)));

 NOTE
 * It's recommended to use binning_fast.m to set up the cell array from
   ungridded data.

 See also: bin, binning_fast, bin_nd

 modified by Salomon Eliasson
 2010-07-08 Oliver Lemke

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

DOWNLOAD ^

binned_statistics.m

SOURCE CODE ^

0001 function out = binned_statistics(data_bins, statistics, filter, replace, opt)
0002 %% BINNED_STATISTICS Calculate statistics for a cell array of binned data.
0003 %
0004 % This functions calculates statistics for binned data. data_bins has to
0005 % be a cell array where each cell contains an array of values.
0006 % Each function given in the statistics parameter is called for each
0007 % cell of data_bins. Optionally, a filter function can be passed which is
0008 % applied to the binned data.
0009 %
0010 % FORMAT   out = binned_statistics(data_bins, statistics, filter, replace, opt)
0011 %
0012 % OUT   out          Structure containing the results for each applied
0013 %                    statistics function.
0014 % IN    data_bins    Cell of gridded vectors of data.
0015 %       statistics   Cell array of statistic function references.
0016 %       filter       Function to filter the binned data.  Function is
0017 %                    expected to return a subset of the original data, i.e.
0018 %                    @(X)X(X>0).  May also be cell thereof with multiple.
0019 %       replace      replace empty cells with <replace> (optional argument).
0020 %                         "replace" may also be a cell with as many elements as there are function
0021 %                         handles that you plan to use,
0022 %                         e.g., replace = {[0 0 0],NaN,-9} for 3 suitable
0023 %                         function handles. If "replace" is not a cell, the same
0024 %                         entry will be used for each function handle
0025 % OPT         structure of extra options:
0026 %       opt.dataClass = 'class' (e.g., 'single'); This ensures
0027 %                   that all the data in the cell is your class of choosing
0028 %
0029 % EXAMPLES
0030 % * Calculate number of elements per bin, mean value for each bin:
0031 %   out = binned_statistics(data_bins, {@numel, @mean});
0032 %
0033 % * Calculate mean and standard deviation, ignore all elements smaller
0034 %   than zero by passing the filter criteria as an anonymous function:
0035 %   out = binned_statistics(data_bins, {@mean, @std}, @(x)(x(x>=0)));
0036 %
0037 % NOTE
0038 % * It's recommended to use binning_fast.m to set up the cell array from
0039 %   ungridded data.
0040 %
0041 % See also: bin, binning_fast, bin_nd
0042 %
0043 % modified by Salomon Eliasson
0044 % 2010-07-08 Oliver Lemke
0045 
0046 if ~exist('opt', 'var')
0047     opt = struct();
0048 end
0049 
0050 assert(iscell(statistics),['atmlab:' mfilename ':badInput'],'function handles must be in a cell')
0051 if exist('filter','var') && ~isempty(filter)
0052     assert( isa( filter, 'function_handle' )||iscell(filter),['atmlab:' mfilename ':BadInput'],'filter must be a function handle or cell thereof')
0053     if iscell(filter)
0054         for i = 1:length(filter)
0055             data_bins = cellfun(filter{i}, data_bins, 'UniformOutput', false);
0056         end
0057     else
0058         data_bins = cellfun(filter, data_bins, 'UniformOutput', false);
0059     end
0060 end
0061 
0062 for i = 1:length(statistics)
0063     try
0064         A.(func2str(statistics{i}))=0; %#ok<STRNU> % it like a "isvalidfieldname" test
0065         statname= func2str(statistics{i});
0066     catch ME
0067         if strcmp(ME.identifier,'MATLAB:AddField:InvalidFieldName')
0068             statname = sprintf('statistic%.0f',i);
0069         else
0070             ME.rethrow();
0071         end
0072     end
0073     
0074     out.(statname) = cellfun(statistics{i}, data_bins, 'UniformOutput', false);
0075 
0076 end
0077 
0078 F = fieldnames(out)';
0079 for i = 1:length(F)
0080     
0081     % ---------------
0082     % assign relace values to empty cells
0083     if exist('replace','var')
0084         
0085         if ~iscell(replace), replace={replace};end
0086         if length(replace)==1, replace=repmat(replace,1,length(F));end
0087         
0088         
0089         % putting back [] if the input was empty to begin with would be desirable, since e.g. nansum([])=0,
0090         %
0091         test =  cellfun('isempty',data_bins) | cellfun('isempty',out.(F{i}));
0092         if any(test(:)) && ~all(test(:))
0093             % find a cell that is not empty and check if the class matches the
0094             % class of the replace value
0095             x = cellfun(@isempty,data_bins);
0096             x = data_bins(~x);
0097             if ~strcmp(class(replace{i}),class(x{1})) && ~isfield(opt,'dataClass')
0098                 warning(['atmlab:' mfilename ':dataClass'],...
0099                     ['replace  value/s is not the same class as data_bins\n'...
0100                     'E.g. this means you cannot call cell2mat without an error\n'...
0101                     'replace value/s is/are class: "%s". data class is: "%s"'],...
0102                     class(replace{i}),class(data_bins{1,1}))
0103             end
0104             out.(F{i})(test)=replace(i);
0105         elseif all(test(:))
0106             logtext(atmlab('OUT'),'Data is empty')
0107         end
0108     end
0109     
0110     % -------------------
0111     % Make sure all the data is the same class
0112     if isfield(opt,'dataClass')
0113         if any(~cellfun(@(x)(strcmp(class(x),opt.dataClass)),out.(F{i})(:)))
0114             out.(F{i}) = cellfun(@(x)(cast(x,opt.dataClass)), out.(F{i}), 'UniformOutput', false);
0115         end
0116     end
0117 end

Generated on Mon 15-Sep-2014 13:31:28 by m2html © 2005