MATLAB: Is there a way to average sequential data on an array and then be able to split the array

arrayaveraging array dataaveraging sequential datafor looploopsequentialsequential datasplit array

I want to be able to split an array of n rows and 5 columns into sections every time the data of a specific column (let's call it column3) crosses zero, and every time there is a peak or valley. I want the split of the array to happen to all the data (the conditions are based on column3, but are applied to all the columns).
The data also has repeated values for the whole data set; for those values I want to average the data of each column by considering the data that was averaged for a specific column per section.
if true
%code example
column3 = [-6 -6 -6 -6 -5 -5 -3 -3 -3 -1 -1 -1 0 0 2 2 2 3 3 5 5 5 5 6 6 6 6 4 4 4 3 3 3 3 3 3 3 2 2 2 1 1 1 1 0 0 -1 -1 -2 -3 -5 -5 -5 -5 -5 -5 -5 -6 -6 -6];
end
I want this to end up looking like
if true
%code result
column3_1 = [-6 -5 -3 -1 0]
column3_2 = [0 2 3 5 6]
column3_3 = [6 4 3 2 1 0]
column3_4 = [0 -1 -5 -3 -5 -6]
end
Then these changes should be also applied to the other columns based on the rows that were averaged for column3.
—–
My line of thought is first I must apply a code to average all the values that are repeated and in sequence using a loop, then separate the sections based on peaks, valleys, and crossing zeroes.
if true
% code thought process
%first average all values
column3_avg = [-6 -5 -3 -1 -0 2 3 5 6 4 3 2 1 0 -1 -2 -3 -5 -6]
%then divide into sections
column3_1 = [-6 -5 -3 -1 0]
column3_2 = [0 2 3 5 6]
column3_3 = [6 4 3 2 1 0]
column3_4 = [0 -1 -5 -3 -5 -6]
end
The main issue is that I can't seem to average only equal sequential data. Is there an effective way to do this on Matlab with a loop or am I better off doing it all by hand?
Thank you in advance

Best Answer

The modern and easy way to do what you want is certainly not by hand, and not with a loop either:
demomatrix = rand(60, 10);
demomatrix(:, 3) = [-6 -6 -6 -6 -5 -5 -3 -3 -3 -1 -1 -1 0 0 2 2 2 3 3 5 5 5 5 6 6 6 6 4 4 4 3 3 3 3 3 3 3 2 2 2 1 1 1 1 0 0 -1 -1 -2 -3 -5 -5 -5 -5 -5 -5 -5 -6 -6 -6];
%averaging of identical consecutive values:
groupids = cumsum([1; diff(demomatrix(:, 3))~=0]);
averagedmatrix = splitapply(@(rows) mean(rows, 1), demomatrix, groupids)
%splitting at 0 and direction reversal:
groupids = cumsum([false; diff(sign(diff(averagedmatrix(:, 3))))~=0; false] ...identify change of direction
| averagedmatrix(:, 3) == 0) + 1; %identify zeros
splitaverage = splitapply(@(rows) {rows}, averagedmatrix, groupids);
Now, you want the transition point to belong to both side. A bit unusual, but can be adjusted after the fact, with a loop indeed:
for row = 1:numel(splitaverage)-1
splitaverage{row}(end+1, :) = splitaverage{row+1}(1, :);
end
celldisp(splitaverage)
Note that the result is stored in a cell array. Do not create separate variables for it, use indexing. Instead of your colum3_4, use
splitaverage{4}