3
$\begingroup$

For simplicity, I give a (3,3) matrix below, though my matrix is of a larger dimension. My objective is, after some matrix manipulations, to select Maximum element(s) in a row and a column, and place zero all the cells except the maximum elements.

mat = {{1, 4, 5}, {1, 2, 4}, {4, 1, 2}};
one = {1, 1, 1};
colTot = one.mat;
rowTot = mat.one;

colStd = Table[matColStd[i, j] = mat[[i, j]]/colTot[[j]], 
{i,3}, {j,3}]//N
rowStd = Table[matRowStd[i, j] = mat[[j, i]]/rowTot[[j]],
{j,3}, {i,3}] // N

solColMat = {{0,0.5714,0.4545}, {0,0, 0}, {0.6666,0,0}};

solRowMat ={{0,0,0.5}, {0,0,0.5714},{0.5714,0,0}};

The above Code column-wise standardizes mat, denoted by colStd. Using the same matrix mat I also introduce a row-standardization rowStd. The standardization of the Code works just fine.

My purpose is to create two new matrices solColMat and solRowMat, which respectively select maximum element(s) from each column and from each row. Non-maximum elements are converted to zeros. The final matrices, solColMat and solRowMat, are given above for clarification purposes.

I would like to have your help.

Thanks.

$\endgroup$
3
$\begingroup$
rowStd = Normalize[#, Total] & /@ mat

{{1/10, 2/5, 1/2}, {1/7, 2/7, 4/7}, {4/7, 1/7, 2/7}}

colStd = Transpose[Normalize[#, Total] & /@ Transpose[mat]]

{{1/6, 4/7, 5/11}, {1/6, 2/7, 4/11}, {2/3, 1/7, 2/11}}

maxSelect = Map[Clip[#, {Max @ #, ∞}, {0, 0}] &];

solRowMat  = maxSelect @ rowStd 

{{0, 0, 1/2}, {0, 0, 4/7}, {4/7, 0, 0}}

solColMat = Transpose @ maxSelect @ Transpose @ colStd

{{0, 4/7, 5/11}, {0, 0, 0}, {2/3, 0, 0}}

Alternative ways to select the maximum from each row:

maxSelect2 =  Map[#  UnitStep[# - Max @ #]&];

maxSelect3 = Map[Threshold[#, {"LargestValues", 1}]&];

The last one is more flexible in that you can change 1 to k to take the largest k elements in each row and set the rest to 0.

$\endgroup$
  • $\begingroup$ In the case of a matrix, say (100,100), I may have to choose not the maximum only but the largest two or three elements in each matrix. Would it be feasible in your Code to do so? $\endgroup$ – Tugrul Temel Aug 16 at 9:27
  • 1
    $\begingroup$ @Tugrul, for largest k elements you can try maxSelect3 replacing 1 with k. $\endgroup$ – kglr Aug 16 at 9:44
  • 1
    $\begingroup$ You can multiply rowStd with 1- IdentityMatrix[3] or subtract from rowStat -Max[mat] IdentityMatrix[3] before using maxSelect (Similarly for colStd.) $\endgroup$ – kglr Aug 16 at 9:50
  • 1
    $\begingroup$ @kglr the Threshold thing is pretty handy, never used it before. So many functions are there to get used to :) By the way +1. $\endgroup$ – PlatoManiac Aug 16 at 9:57
  • 1
    $\begingroup$ @PlatoManiac, thank you for the vote. Clip with an appropriate threshold in the second argument is probably faster, but Threshold is really convenient. $\endgroup$ – kglr Aug 16 at 10:03
4
$\begingroup$

I will do something like this. Unitize is pretty useful here.

With[{max = Max@#}, max Unitize[#, max]] & /@ rowStd

{{0., 0., 0.5}, {0., 0., 0.571429}, {0.571429, 0., 0.}}

For the colums first Transpose to get to rows and then transpose back.

With[{max = Max@#}, max Unitize[#, max]] & /@ (Transpose@colStd) // Transpose

{{0., 0.571429, 0.454545}, {0., 0., 0.}, {0.666667, 0., 0.}}

Note

This works when the maximum entry (in each row or column) is positive. However the methods given by @kglr explore more general options and UnitStep will probably give speed benefits for large matrices.

$\endgroup$
  • $\begingroup$ I absolutely agree with your comments. Thank you for your help. $\endgroup$ – Tugrul Temel Aug 18 at 6:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.