0
votes

I have an annual data set:

Jday = datenum('2009-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
    datenum('2009-12-31 23:00','yyyy-mm-dd HH:MM');
DateV = datevec(Jday);
dat = 1+(10-1).*rand(length(Jday),10);
noise = 10*sin(2*pi*Jday/32)+20;
for i = 1:size(dat,2);
    dat2(:,i) = dat(:,i)+noise';
end

which represents temperature measurements recorded through a water column. I would like to calculate the temperature range between 06:00 and 18:00 for each day so that I end up with 365 values for each depth so a final matrix of 365x10.

I can specify the individual days by:

[~,~,b] = unique(DateV(:,2:3),'rows');

But I cant work out how to only consider values recorded between 06:00 am and 18:00 pm. Could anyone provide some information about the best possible way of doing this?

Amended: slightly long answer

Jday = datenum('2009-01-01 00:00','yyyy-mm-dd HH:MM'):1/24:...
    datenum('2009-12-31 23:00','yyyy-mm-dd HH:MM');
DateV = datevec(Jday);
dat = 1+(10-1).*rand(length(Jday),10);
noise = 10*sin(2*pi*Jday/32)+20;
for i = 1:size(dat,2);
    dat2(:,i) = dat(:,i)+noise';
end

for i = 1:size(dat2,2);
    data = [DateV(:,4),dat2(:,i)]; % obtain all hours from DateV array

    dd = find(data(:,1) == 6); % find 06:00
    dd(:,2) = find(data(:,1) == 18); % find 18:00

    for ii = 1:size(dd,1);
        result(ii,i) = range(data(dd(ii,1):dd(ii,2),2)); % calculate range
    end
end
2
I don't understand how you want to represent the temperature range using only one value.Eitan T
temperature range is between 06:00 and 18:00 for each day therefore there are 13 valuesEmma
This is still unclear. You want to end up with a 365-by-10 matrix. I infer that 365 corresponds to the number of days and 10 is the number of measurements. Where does this 06:00-18:00 temperature comes into play? Do you want to average the values in this time period?Eitan T
Correct for the matrix. If you look in the variable DateV it will have the time of day in hours 'DateV(:,4)' so for the first day i.e. 2009-01-01 I would like to calculate the range of temperatures between row 7 and row 18 i.e. 06:00 and 18:00 respectively. Therefore for the first day and the first measurement (depth) I could calculate this by: range(dat2(7:18,1)) I would then need to repeat this for the second column then third and so on, then repeat this procedure for the second day which will start in row 25. Is this any clearer?Emma
I think so. I've posted an answer, hope it helps.Eitan T

2 Answers

2
votes

If range is fed with a matrix, it operates on each column independently. We can use this to prepare a matrix where each column contains the values for the time interval of 06:00 to 18:00, and apply range.

  1. The tricky part is manipulating your 365x24-by-10 matrix to get the columns right:

    A = permute(reshape(dat2', [10, 24, 365]), [2, 1, 3]);
    

    This should result in 3-D 24x10x365 matrix, from which rows 7 to 18 can be extracted.

  2. The next step is to apply range and transform the result back into a 2-D 365x10 matrix:

    result = permute(range(A(7:18, :, :)), [3, 2, 1]);
    

Therefore, the full solution is:

A = permute(reshape(dat2', [10, 24, 365]), [2, 1, 3]);
result = permute(range(A(7:18, :, :)), [3, 2, 1]);

EDIT:
To make the solution even more generic, you can use DateV to obtain the indices of the desired rows:

idx = DateV(1:24, 4) >= 6 & DateV(1:24, 4) < 18;

and then use it in the solution like so:

A = permute(reshape(dat2', [10, 24, 365]), [2, 1, 3]);
result = permute(range(A(idx, :, :)), [3, 2, 1]);
2
votes

Hourly date range between 01-Jan-1987 and 31-Dec-1987:

start_date = datenum(1987,01,01,00,00,00)
end_date = datenum(1987,12,31,23,00,00)
interval = datenum(1987,0,0,1,0,0)-datenum(1987,0,0,0,0,0) % 1 hour interval

date_range = [start_date:interval:end_date]

Very simple and works also for leap years.