Finding maximum and minimum values of an array by specifying the range.
Afficher commentaires plus anciens
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 commentaires
José-Luis
le 6 Fév 2013
What's the format of the date?
doc accumarray
Image Analyst
le 6 Fév 2013
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.
Réponse acceptée
Plus de réponses (3)
Youssef Khmou
le 6 Fév 2013
Modifié(e) : Youssef Khmou
le 6 Fév 2013
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 commentaires
José-Luis
le 6 Fév 2013
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.
Youssef Khmou
le 6 Fév 2013
true, but date details are not mentioned , in order to select lines with same date .
minotshing maza
le 6 Fév 2013
Youssef Khmou
le 6 Fév 2013
hi, give more details about the date column .
minotshing maza
le 6 Fév 2013
Modifié(e) : Jan
le 6 Fév 2013
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.
Azzi Abdelmalek
le 6 Fév 2013
Modifié(e) : Azzi Abdelmalek
le 6 Fév 2013
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 commentaires
José-Luis
le 6 Fév 2013
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.
Image Analyst
le 6 Fév 2013
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()!
Jan
le 6 Fév 2013
@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.
Catégories
En savoir plus sur Resizing and Reshaping Matrices dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!