0

I currently am seeking a way to use Matlab to help define a heatwave event at a certain station. For my situation, a heatwave is where the departure from normal for a high or low temperature is in the 95 percentile (a "relaxed" heatwave) or in the 99 percentile (a "strict" heatwave).

I used a .csv file that had daily maximum and minimum temperatures, along with the respective departures. From here I was able to break the data into the time frame I wanted, and then calculate the thresholds. There are four different thresholds -- the minimum and maximum temperature departure in the 95 percentile and the minimum and maximum temperature departure at the 99 percentile.

Currently I have four matrices that have data for each respective threshold. Here is a small portion of the matrix that met the maximum temperature departure threshold (m1):

694158    99    14    64    1
694159    99    13    68    5
694179    98    13    63    1
694180    98    14    74   12
694183   100    16    70    8

The first column represents the serial date number, and the rest of the columns are temperature information (max, max departure, min, min departure).

So here is my question: I cannot find a way to go through the serial date numbers and see if there are three (or more) consecutive days in a row.

The best help I could find online was this mathworks post but the solution wouldn't append any information into a matrix.

If someone could point me in the right direction, or point me towards a resource to help me out, I would highly appreciate it!

Thanks in advance.

3
  • 1
    What do you mean by consecutive? Are you referring to the serial date numbers and seeing if they follow a sequence? For example, would 694158, 654159 and 694160 be considered a sequence of three consecutive days? Seeing as how 694160 is not in the column, would this only count as two consecutive days? Commented Jun 10, 2014 at 20:41
  • Yes, I want to be able to look through the date column and pick out the rows that have a 3 day (or longer) sequence (e.g. 694158, 654159 and 694160) for the whole entire matrix Commented Jun 10, 2014 at 20:48
  • That's not so bad. Give me 5 minutes. Commented Jun 10, 2014 at 20:53

3 Answers 3

1

Let M denote your matrix, and n the minimum number of consecutive days you want (3 in your example). Then:

ind = find(conv(double(diff(M(:,1))==1), ones(n-1,1))==n-1)-n+2; %// starts
ind = bsxfun(@plus, ind, 0:n-1); %// fill n-1 subsequent row indices
ind = unique(ind(:)); %// make unique
result = M(ind,:); %// keep only those rows
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, I'm aware I'm asking this way after you posted this answer, but I figured that this would be better than starting a new question. Would there be any way to modify this code to find the maximum number of consecutive days? So, for example, if I have 3 + day consecutive day events in a matrix, could I modify this code to isolate only the 3 day events? or 2 day events? Thank you!
@climatefreak Not sure what you mean... besides, this seems to really be a new question. I suggest you post it as a new question, including an example with input and desired output
0

Looking at your comments, you wish to find the rows that have three or more consecutive dates. The basic algorithm is that we have a sliding window of size 3. We check to see if the difference between the last point and the first point is 2. For example, the difference between 694160 and 694158 is 2, and this denotes 3 consecutive days. Whenever we see that there is a difference of 2, this means that these three rows denote a consecutive run.

We can implement this sliding window mechanism by using the im2col function. This is assuming you have the image processing toolbox installed (crosses fingers). We can then segment our date array into overlapping sets of 3. We then implement the logic that we have above and see which areas have a difference of 2. At this point, these locations denote the starting position of where the consecutive run is. Bear in mind that if you want to capture consecutive runs of > 3, we are going to have duplicate runs. For example, if we had a run of 4 (let's say from 694158 to 694162), we would have a run at locations 1 to 3, and 2 to 4. We will then need to eliminate duplicates so that we can finally capture our unique rows. Without further ado, here's some code with an example. This is the example I'm going to use. Assume that A is the column of dates that you have extracted from your matrix. I've artificially created it here to make the example self-contained.

A = [(694158:694160)'; 694161; 694179; 694180; 694183; (694160:694162)';(695000:695005)'];

A =

  694158
  694159
  694160
  694161
  694179
  694180
  694183
  694160
  694161
  694162
  695000
  695001
  695002
  695003
  695004
  695005

Now, here's the logic I implemented:

%//Place our array into neighbourhoods of 3
columns = im2col(A, [3, 1]);
%//Find the difference
diffColumns = bsxfun(@minus, columns, columns(1,:));
%// Check to see which columns have a max difference of two
maxDiff = find(diffColumns(3,:) == 2);
%//Find those rows that satisfy our condition
rowsNonUnique = arrayfun(@(x) x:x+2, maxDiff, 'UniformOutput', false);
% // Eliminate duplicates and transform back
rowsFinal = unique(cell2mat(rowsNonUnique));

rowsFinal =

Columns 1 through 12

 1     2     3     4     8     9    10    11    12    13    14    15

Column 13

 16

As you can see from the data, we need rows 1-4 and 8-16 as it agrees with what we know to be consecutive rows of at least 3 or more.

Now if you want to append this to your matrix that you have above, you can do the following, assuming your data is stored in the variable matrix

indicator = zeros(size(matrix,1),1);
indicator(rowsFinal) = 1;
matrix(:,6) = indicator;

This will create a sixth column, and what this will show you is anything that has the value of 1 means that this is a row you need to consider, while 0 means you skip it.

Good luck!

Comments

0

Here you go, this ought to do it:

count = 0;
for ii = 2:size(tempArray, 1)
    if tempArray(ii, 1) == (tempArray(ii-1, 1)+1)
        count = count + 1;
        if count >= 3;
            tempArray(ii-2:ii, 6) = 1;
        end 
    else
        count = 0;
    end 
end
%// This last line should work... but I haven't tested it.
consecArray = tempArray(find(tempArray(:,6)==1));

The code iterates through each element of your array, compares it to the previous, and if three in a row are found to be sequential, sets a sixth row to 1. Thus, after running this script, you will have a matrix where each row that is part of three or more sequential days will have a value indicating as much.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.