Sliding window function over column vector, Help!
Show older comments
I have a dataset with months, location (xyz) and magnitude. There is no actual time values but it is ordered in time. I want to create a sliding window function over the column vector of magnitude to perform a calculation and store the output. The data is attached. The below code extracts data for month 7 which is July and plots a regression line for the data in the whole month. The total number of data points in July is 22708. How do I run a moving window of 500 points every one point (eg 1 to 500, 2 to 501, 3 to 502) over the dataset to get all the magnitudes for each window and then I will perform a calculation and store the output. eg 1 to 500 = b1, 2 to 501 = b2, 3 to 502=b3 etc, where b1,b2,b3 are the calculated results that must be stored in a vector.
%%extract data for a specific month
month7=month(month==7); %want to know how many values were taken at the 7th month
size7=size(month7);%get the size of the data set
value7=size7(1,1);%since matlab works in vectors, we only want the first row and fist column
M7=M(1:value7);%search for the magnitudes for that month
tbl7=tabulate(M7);
A7=tbl7(:,1:2);
Bfreq7=tbl7(:,2);
Bcumfreq7=cumsum(Bfreq7,1,'reverse');
Bmag7=tbl7(:,1);
Nlog7=log10(Bcumfreq7);
[p,S] = polyfit(Bmag7,Nlog7,1);
[y_fit,delta] = polyval(p,Bmag7,S);
plot(Bmag7,Nlog7,'bo')
hold on
plot(Bmag7,y_fit,'r-');
plot(Bmag7,y_fit+2*delta,'m--',Bmag7,y_fit-2*delta,'m--')
title('Linear Fit of Data with 95% Prediction Interv
I tried running a moving window function but it is not indexing the M7 values.
L=M7;
window=100;
for k1=1:L-window+1
datawin(k1,:)=k1:k1+window-1;
end
3 Comments
Guillaume
on 23 Nov 2019
"and then I will perform a calculation". What calculation? It's very easy to perform calculations on a sliding window, however which method is bestdepends on the calculation.
Some comments on your code:
- Don't tie your variable names to the month (i.e. drop the 7 at the end of the variable names), chances are you'll want the same calculation for each month which will be much easier if your variables are not tied to a month. Numbered or sequentially named variables are always a bad idea.
- It's unclear what the relationship between month7 and M is and it's unlikely you're actually extracting the rows that correspond to month 7 from M.
- To get the height of a matrix use:
value7 = size(month7, 1); %pass the dimension you want to query to size. Note that value is not a good variable name for a height.
- Avoid creating variables that are used only once. You could replace:
tbl7=tabulate(M7);
A7=tbl7(:,1:2);
Bfreq7=tbl7(:,2);
Bcumfreq7=cumsum(Bfreq7,1,'reverse');
Bmag7=tbl7(:,1);
Nlog7=log10(Bcumfreq7);
[p,S] = polyfit(Bmag7,Nlog7,1);
[y_fit,delta] = polyval(p,Bmag7,S);
by
frequency_table = tabulate(M7);
logcumulative_frequency = log10(cumsum(frequency_table(:, 3), 1, 'reverse'));
magnitude = frequency_table(:, 1);
[p, S] = polyfit(magnitude, logcumulative_frequency, 1);
[y_fit, delta] = polyval(p, magnitude, S);
which is clearer.
Thashen Naidoo
on 23 Nov 2019
Thashen Naidoo
on 23 Nov 2019
Answers (2)
Guillaume
on 24 Nov 2019
"The data has months 7 to 10 and labelled them as M7, M8, M9, M10 to help me remember the months."
Do not do that! Numbered variables are always a bad idea. Your numbered variables will force you to copy/paste your code for each month just to change the variable name. It will make everything more complicated, not simpler.
"Every M that is recorded for July has a value 7 attributed to it in another row. The same for August with a value 8 in another row etc. I basically indexed for the month == 7 to get the size of that and then extracted the magnitude values for that size in the column with magnitudes"
So you basically have a matrix with at least two columns with one column being the month and the other the magnitude. You may consider using a table for this as tables have plenty of features suited to this type of data. In particular, grouptransform would allow you to do your calculation for all the months at once.
Assuming that M is the magnitude column of your matrix and month the month column, your initial extraction of the values corresponding to a month does not work. Assuming that there are N rows corresponding to a month, your code is ignoring which actual rows these are and always extract the first N rows of the matrix. The proper code would be:
thismonthdata = M(month == 7);
I'm a bit confused by your equation "b=loge/(M_ave - M_min)",
is by definition 1. I'm assuming your actual equation is
, in which case it can be implemented very simply as
is by definition 1. I'm assuming your actual equation is
, in which case it can be implemented very simply aswindowsize = 100
b = log(movmean(M, windowsize, 'EndPoints', 'discard') - movmean(M, windowsize, 'EndPoints', 'discard'));
There's no built-in function to perform your second calculation over a window, so you will have to use a loop. In that case, you may as well do the above in the loop as well, it would go like:
windowsize = 100;
for start = 1:numel(M)-windowsize+1
windowdata = M(start+(1:windowsize));
b = log(mean(windowdata) - min(windowdata)); %better variable name needed. I'm unclear what b is used for
frequency_table = tabulate(windowdata);
logcumulative_frequency = log10(cumsum(frequency_table(:, 3), 1, 'reverse'));
magnitude = frequency_table(:, 1);
[p, S] = polyfit(magnitude, logcumulative_frequency, 1);
[y_fit, delta] = polyval(p, magnitude, S);
%... store the results somewhere. I'm unclear what you want to do here.
end
1 Comment
Thashen Naidoo
on 24 Nov 2019
Thashen Naidoo
on 24 Nov 2019
Categories
Find more on Linear Regression in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!