Finding maximum and minimum values of an array by specifying the range.

I have an array of very large size 10000*2,the first and second column representing date and temperature respectively.Readings were taken not less than ten times per day.How will i specify the range to compute the max and min temperature of each day?Any help will be highly appreciated.
[EDITED, Jan, copied from the comment section]
here is sample of my data:
date temp
01-01-11 11.9
01-01-11 12
01-01-11 13.2
01-01-11 15
01-01-11 17.6
01-01-11 21.2
01-01-11 21.6
01-01-11 20.9
01-01-11 20.1
01-01-11 19.8
01-01-11 19.1
01-01-11 17.8
02-01-11 17.3
02-01-11 16.9
02-01-11 16.7
02-01-11 16.4
and so on... It is a two column matrix but i can't display it well here. Hope you understand.

3 Comments

People below are making assumptions on what your dates are. Don't make them waste their time - give an example of some date readings that span more than one day so we can see what they look like. For example, is the number just representing the day, or is the time of day also encoded into the number so that all numbers on a single day will not be the same number. By the way, 20,000 elements is really rather tiny, not "very large" - not even close.
Please post all necessary information in the question, not as comment to answers. Then readers have the chance to recognize the problem as fast as possible.
I think 20'000 elements is more than "rather tiny", but far from "large". "Very large" would mean, that more than half of the computers memory is used, e.g. 500'000'000'000 elements of type double. Then my approach is not sufficient, because the logical indexing becomes inefficient.
But I agree with Image Analyst: The more details you explain, the less of your and our time is wasted by guessing.

Sign in to comment.

 Accepted Answer

Using accumarray(), assuming data is a two column array where the first column is Matlab's serial date number:
idx = floor(data(:,1)); %Not strictly necessary given your data
dailyIdx = idx - min(idx) + 1;
dailyT = unique(idx);
your_min = accumarray(dailyIdx,data(:,2),[],@min);
your_max = accumarray(dailyIdx,data(:,2),[],@max);
your_new_mat = [dailyT your_min]; %e.g.

More Answers (3)

hi, data is 10000x2, assume that each day represents 10 readings then you have : 1000x2 "days" : You can adjust the loop to pick up the max,min every 10 elements :
N=10000;
data=rand(N,2); % Here you Load your DATA, instead of rand(m,n)
MaxMin=zeros(N/10,3); % First column MAX, second is MIN and 3rd is the date
index=1;
for tt=1:N-10
MaxMin(index,1)=max(data(tt:tt+10,1)); % Max of 10 elements
MaxMin(index,2)=min(data(tt:tt+10,1)); %Min of 10 elements
MaxMin(index,3)=data(tt+5,2); % date taken as 5th elemnt among 10
index=index+1;
end
plot(MaxMin(:,1:2)) % This should give two remarquably separated lines
%: top/bottom

6 Comments

That can be done without loops, and will only work if there are 10 data per day. The OP seems to suggest that the number of data will vary depending on the day.
true, but date details are not mentioned , in order to select lines with same date .
since the numbers of readings taken per day are not the same,I don't think that this will work.But anyway thanks for your concern!
hi, give more details about the date column .
here is sample of my data:
date temp
01-01-11 11.9
01-01-11 12
01-01-11 13.2
01-01-11 15
01-01-11 17.6
01-01-11 21.2
01-01-11 21.6
01-01-11 20.9
01-01-11 20.1
01-01-11 19.8
01-01-11 19.1
01-01-11 17.8
02-01-11 17.3
02-01-11 16.9
02-01-11 16.7
02-01-11 16.4
and so on... It is a two column matrix but i can't display it well here. Hope you understand.
I've formatted your matrix, see Format in the forum.
Your matrix looks very strange: While the 2nd column looks like a numeric value, the 1st column must be a string. Therefore it must be a cell matrix and it would be important to mention this directly.

Sign in to comment.

dat=datestr(data(:,1),'dd-mmm-yyyy HH:MM:SS') % data your 1000*2 array
dat1=datevec(dat)
day=dat1(:,3)
[a,b,c]=unique(dat1(:,1:3),'rows')
n=numel(b);
b0=1
for k=1:numel(b)
mindata{k}=min(data(b0:b(k)));
maxdata{k}=max(data(b0:b(k)));
if k<n
b0=b(k)+1
end
end
Assuming that the date is in Matlab's serial date number format (if not, use datenum to get it):
data = <your data matrix comes here>
days = floor(data(:, 1)); % Remove the time
uniqDays = unique(days); % sorted already
nDays = length(uniqDays);
minTemp = zeros(1, nDays); % Pre-allocate!
maxTemp = zeros(1, nDays); % Pre-allocate!
for iDay = 1:nDays
match = (days == uniqDays(iDay));
Temp = data(match, 2);
minTemp(iDay) = min(Temp);
maxTemp(iDay) = max(Temp);
end
This would be much nicer with accumarray and perhaps even faster. The need to run accumarray twice might reduce the speed advantage. But reading the -in my eyes strange- documentation of the accumarray command will take more time than you win finally.
[EDITED] According to your description of the input "01-01-11 11.9" I guess this might work:
days = datenum(data(:, 1), 'dd-mm-yy');
tempVec = cat(1, data{:, 2});
...
Temp = tempVec(match);

3 Comments

I totally agree with the gripe against the accumarray documentation. It took me forever to sort of understand the function. And that was through trial-and-error more than through an understanding of the documentation.
I'm not yet to the point of accumarray enlightenment. The documentation still looks like gibberish to me. It's about all I can handle just to understand all the complexities of blockproc()!
@Image Analyst: Actually it is trivial: It does exactly what my FOR loop above does, but as fast MEX with a smaller memory footprint. But, at some step on the a stairway of abstraction I loose the connection:
A = accumarray([1 1; 2 1; 2 3; 2 1; 2 3], 101:105, [2 4], @max, NaN)
Anybody, who can explain this command with <= 3 sentences, owes my respect, and if possible I offer an answer for free as service in return.

Sign in to comment.

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!