简体   繁体   中英

find common value of one matrix in another matrix

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM