KatyB
KatyB

Reputation: 3980

find the indices to calculate the monthly averages of some hours in a time series

If I have one year worth of data

Jday = datenum('2010-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
    datenum('2010-12-31 23:00','yyyy-mm-dd HH:MM');
dat = rand(length(Jday),1);

and would like to calculate the monthly averages of 'dat', I would use:

% monthly averages
dateV = datevec(Jday);
[~,~,b] = unique(dateV(:,1:2),'rows');
monthly_av = accumarray(b,dat,[],@nanmean);

I would, however, like to calculate the monthly averages for the points that occur during the day i.e. between hours 6 and 18, how can this be done?

I can isolate the hours I wish to use in the monthly averages:

idx = dateV(:,4) >= 6 & dateV(:,4) <= 18;

and can then change 'b' to include only these points by:

b(double(idx) == 0) = 0;

and then calculate the averages by

monthly_av_new = accumarray(b,dat,[],@nanmean);

but this doesn't work because accumarray can only work with positive integers thus I get an error

Error using accumarray First input SUBS must contain positive integer subscripts.

What would be the best way of doing what I've outlined? Keep in mind that I do not want to alter the variable 'dat' when doing this i.e. remove some values from 'dat' prior to calculating the averages.

Thinking about it, would the best solution be

monthly_av = accumarray(b(idx),dat(idx),[],@nanmean);

Upvotes: 0

Views: 312

Answers (1)

Luis Mendo
Luis Mendo

Reputation: 112659

You almost have it. Just use logical indexing with idx in b and in dat:

monthly_av_new = accumarray(b(idx),dat(idx),[],@nanmean);

(and the line b(double(idx) == 0) = 0; is no longer needed).

This way, b(idx) contains only the indices corresponding to your desired hour interval, and data(idx) contains the corresponding values.

EDIT: Now I see you already found the solution! Yes, I think it's the best approach.

Upvotes: 1

Related Questions