How to modify a for loop script to conduct calculation on a sliding window

5 vues (au cours des 30 derniers jours)
Nicholas Barber
Nicholas Barber le 19 Juin 2017
Commenté : Chris Turnes le 6 Juil 2017
I'm working with some tables I've made that are a continuous time-record of hour-by-hour observations at a given site. What I want to do is take this long term record, calculate weekly rates of change (i.e. slope), and do so with a sliding window that conducts this calculation every day. The goal of the latter is to create a continuous record of changes in rates.
The first problem I have solved, admittedly inelegantly, with the following code (I apologize for the sloppiness; I'm new to both MATLAB and programming and any tips on how to streamline this code would be appreciated). DLTT is the name of my rounded and continuous record of observations, stored in a table datatype. I should note also that my data contains NaN's, which is why I filter the data before running polyfit in the script:
r = height(DLTT);
coefficients = 0;
count = 0
for i = 1 : r
if rem(i,168) == 0
t = DLTT(i-167:i,:);
validdata = ~isnan(t.TiltMag);
t = t(validdata,:);
x = datenum(t.Date_Time);
x = x - x(1);
y = t.TiltMag;
coefficients = polyfit(x,y,1);
count = count + 1
slope(count) = coefficients(1);
t = [];
end
I really want to know how to make this script, which does the job of calculating weekly rates wonderfully, able to do the same calculation on a sliding window. Since this is hour by hour data, this would mean after index 168 it should repeat the calculation every 24 rows, but I'm not sure how to tell it to do that.
Any help would be appreciated, thank you.

Réponses (1)

Image Analyst
Image Analyst le 19 Juin 2017
Why not just use movmean() or conv()?
  5 commentaires
Chris Turnes
Chris Turnes le 6 Juil 2017
To make a slight correction to Image Analyst's answer, you don't need the time points to be evenly spaced if you use the 'SamplePoints' Name-Value pair to specify your timestamps. If you say, for example, movmean(x,hours(24*7),'SamplePoints',t), then the output value y(i) corresponding to timestamp t(i) would be the average of all points x(j) whose corresponding timestamps t(j) are within the 24*7 hour window centered at t(i).
Chris Turnes
Chris Turnes le 6 Juil 2017
It sounds like what you are looking for is a linear fit of the data in each window, and you care about the slope parameter. Since your data is evenly spaced at hour intervals, you can consider that for any 24*7 = 168 hour, you can fit a least-squares linear model of your data with:
a = V\x;
where V(i,:) = [i-84 1];
So what you're trying to do here is essentially compute s = V\x for a sliding window over the x values.
One approach here is to create the V matrix, factor it, and use it to compute the least-squares fit in every window:
% Take the Q-R decomposition
[Q,R] = qr([(-84:83)', ones(168,1)], 0);
% Convolve the columns of Q with the observations.
y = conv(x, flip(Q(:,1)), 'valid');
y(:,2) = conv(x, flip(Q(:,2)), 'valid');
% Compute the slope and intercepts.
s = y / R;
I've used the 'valid' option here, so you're only getting the windows where there's a full 168 hours worth of data to fit (you'd have to handle the endpoints in a more nuanced way), but you'll see it's equivalent to fitting the slope and intercept for each window:
>> x = randn(300,1);
>> % Create the linear fit matrix
>> V = [(-84:83)', ones(168, 1)];
>> [Q,R] = qr(V,0);
>> % Use it in a sliding window method
>> y = conv(x, flip(Q(:,1)), 'valid');
>> y(:,2) = conv(x, flip(Q(:,2)), 'valid');
>> % Use the result to compute the slope and intercept
>> s = y / R;
>> s(1,:)
ans =
0.0030 -0.0739
>> % Compare against the first valid window.
>> V\x(1:168)
ans =
0.0030
-0.0739

Connectez-vous pour commenter.

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by