I have one matrix MyMatrix 2549x13double
Few example lines from MyMatrix :
-7.80 -4.41 -0.08 2.51 6.31 6.95 4.97 2.91 0.66 -0.92 0.31 1.24 -0.07
4.58 5.87 6.18 6.23 5.20 4.86 5.02 5.33 3.69 1.36 -0.54 0.28 -1.20
-6.22 -3.77 1.18 2.85 -3.55 0.52 3.24 -7.77 -8.43 -9.81 -6.05 -5.88 -7.77
-2.21 -3.21 -4.44 -3.58 -0.89 3.40 6.56 7.20 4.30 -0.77 -5.09 -3.18 0.43
I have identified the maximum value for each row of matrix MyMatrix as following:
[M Ind] = max(MyMatrix, [], 2);
Example lines I obtain in M :
6.95
6.23
3.24
7.20
Now, I would like to select in MyMatrix the 2 values before and after the maximum value as found in M , as I will need to calculate the average of these 5 values. So, in the example, I would like to select:
2.51 6.31 6.95 4.97 2.91
5.87 6.18 6.23 5.20 4.86
-3.55 0.52 3.24 -7.77 -8.43
3.40 6.56 7.20 4.30 -0.77
and to create a new column in MyMatrix with the mean of these 5 values.
I would appreciate any help. Many thanks.
Get the column indices required per row:
colInd = bsxfun(@plus,Ind, -2:2)
Now it will actually be easier to work with your matrix transposed ( MyMatrixT = MyMatrix.'
) since we will be working with linear indexes so let's rather work with
rowIndT = colInd.';
Now we want to convert this Rind
to linear indexes. This is just a case of adding the total number of rows (number of columns in the original) to the column number
linIndT = bsxfun(@plus,rowIndT,0:size(MyMatrixT,1):size(MyMatrixT,1)*(size(MyMatrixT,2)-1))
And finally we extract the values and transpose back
resultT = MyMatrixT(linIndT);
result = resultT.'
result =
2.5100 6.3100 6.9500 4.9700 2.9100
5.8700 6.1800 6.2300 5.2000 4.8600
-3.5500 0.5200 3.2400 -7.7700 -8.4300
3.4000 6.5600 7.2000 4.3000 -0.7700
The new column is just the mean of result:
mean(result,2)
and to append it to your matrix
MyMatrix = [MyMatrix, mean(result,2)]
Now there is still one problem, what happens if a maximum is near the edge (ie if a maximum is in column 2, then two values before the maximum is not defined). How to deal with this will require you to first define the behavior you desire in such situations. But let's assume you want NaN
, then I would do this:
colInd = bsxfun(@plus,Ind, -2:2);
rowIndT = colInd.';
% Bound rowIndT to be between 1 and size(MyMatrixT,1)
rowIndT(rowIndT < 1) = 1;
rowIndT(rowIndT > size(MyMatrixT,1)) = size(MyMatrixT,1);
linIndT = bsxfun(@plus,rowIndT,0:size(MyMatrixT,1):size(MyMatrixT,1)*(size(MyMatrixT,2)-1)); % You can use sub2ind instead for this step
result = MyMatrixT(linIndT).';
% Now go back and put NaNs where they are needed
nanColInd = colInd < 1 | colInd > size(MyMatrix,2);
result(nanColInd) = NaN;
% Now use nanmean to ignore any NaNs when finding the mean
MyMatrix = [MyMatrix, nanmean(result,2)]
One last thing, you might find it more intuitive to use sub2ind
to find the linear indexes. In that case
linIndT = bsxfun(@plus,rowIndT,0:size(MyMatrixT,1):size(MyMatrixT,1)*(size(MyMatrixT,2)-1))
becomes
linIndT = sub2ind(size(MyMatrixT), rowIndT, repmat(1:size(MyMatrixT,2),size(rowIndT,1),1))
This will take avg of 2 elements before and after the maximum and store it in the end column
endRow = size(MyMatrix,2) + 1
for i = 1:size(MyMatrix,1)
MyMatrix(i,endRow) = mean(MyMatrix(i,max(Ind(i)-2,0):min(Ind(i)+2,end)));
end
Update: Sorry I have updated which stores in the last column
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.