6
$\begingroup$

I have a matrix:

enter image description here

I would like to sum all the first non-zero elements of each row so that I get a value of

$$25.5317 + 8.85471 + 6.90018 + 32.9436 + ... $$

and so on and simply ignore zero rows.

Similarly I would like to do the same again for the second non-zero elements from each row so that I get:

$$29.1235 + 11.0472 + 41.2639$$

$\endgroup$
6
$\begingroup$
 tbl = RandomChoice[{.5, .1, .05, .05, .05, .05, .05, .05, .05, .05} ->
     Range[0, 9], {10, 10}];
 tbl//TableForm

enter image description here

Remove all zeros from tbl and add zeros to the right to make a full array:

PadRight[tbl /. (0) -> Sequence[], Automatic] // TableForm

enter image description here

Then sum each column:

 Tr /@ (Transpose@PadRight[tbl /. (0) -> Sequence[], Automatic])
 (* {55, 59, 36, 28, 38, 14, 9} *)

Update: To get a matrix with dimensions {nrows, ncolumns} from PadRight change Automatic to {nrows, ncolumns}. So,

 Tr /@ (Transpose@PadRight[tbl /. (0) -> Sequence[], {10,10}])
 (* {55, 59, 36, 28, 38, 14, 9, 0 ,0, 0} *)
$\endgroup$
  • $\begingroup$ Hi @kguler, seems to work but I originally had 5 columns, now after sorting, it is 4 columns? Why is that? I need to maintain the column to be constant. $\endgroup$ – sebastian c. Nov 16 '12 at 2:27
  • $\begingroup$ @sebastian, to get a matrix with dimensions {nrows, ncolumns} from PadRight change Automatic to {nrows, ncolumns}. (The setting Automatic adds as many columns as needed to remove raggedness.) $\endgroup$ – kglr Nov 16 '12 at 2:37
4
$\begingroup$

Not as nice as the method given by kguler. Nevertheless, as an alternative:

myarray = {{0., 0., 0., 0., 0}, {0., 0., 0., 0., 0},
  {0., 0., 0., 25.5317, 29.1235}, {0., 0., 0., 0., 8.85471}, {0., 0., 
   0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 6.90018}, {0., 
   0., 0., 0., 32.9436}, {0., 0., 0., 0., 29.1235}, {0., 0., 0., 
   2.47854, 11.0472}, {0., 0., 16.1408, 41.2639, 45.7614}, {0., 0., 
   0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}}

(Using Flatten to transpose a ragged array):

Flatten[Select[#, FreeQ[#, 0. | 0] &] & /@ myarray, {2}]

=>

{{25.5317, 8.85471, 6.90018, 32.9436, 29.1235, 2.47854, 16.1408}, {29.1235, 11.0472, 41.2639}, {45.7614}}

Therefore,

Total /@ Flatten[Select[#, FreeQ[#, 0. | 0] &] & /@ myarray, {2}]

=>

{121.973, 81.4346, 45.7614}

Comparing with kguler's method

tbl = RandomChoice[{.5, .1, .05, .05, .05, .05, .05, .05, .05, .05} ->
     Range[0, 9], {10, 10}];
Tr /@ (Transpose@PadRight[tbl /. (0) -> Sequence[], Automatic]) == 
 Total /@ Flatten[Select[#, FreeQ[#, 0. | 0] &] & /@ tbl, {2}]

=>

True

Edit

Better, perhaps, is

Total /@ Flatten[DeleteCases[myarray, 0 | 0., 2], {2}]

However, the best variation on the Flatten approach, I recon, is given below (as a comment) by rm -rf:

Total[Flatten[# /. 0 | 0. -> Sequence[], {2}], {2}] &@myarray

=>

{121.973, 81.4346, 45.7614}

$\endgroup$
  • 1
    $\begingroup$ I was about to write an answer with this same approach. It can also be written as: Total[Flatten[# /. 0|0. -> Sequence[], {2}], {2}]& $\endgroup$ – rm -rf Nov 15 '12 at 18:42
  • $\begingroup$ @rm -rf. That is a nice one! Thanks. $\endgroup$ – user1066 Nov 15 '12 at 19:52
  • $\begingroup$ Tom and @rm-rf, actually I like your method better:). $\endgroup$ – kglr Nov 16 '12 at 3:12
2
$\begingroup$

One can search for the first nonzero element in each row using Cases. Generate a random table:

m = Normal@SparseArray[
      Thread@{RandomInteger[{1, 12}, 14], RandomInteger[{1, 6}, 14]} :> RandomReal[], {12, 6}];

Mathematica graphics

and pick the first match in each row:

Flatten[Cases[#, _?(! PossibleZeroQ@# &), 1, 1] & /@ m]

Or extending the Sequence replacement method in kguler's answer:

m /. {0 | 0. -> Sequence[]} /. {} -> Sequence[] /. {x_?NumberQ, ___} :> x
{0.252222, 0.998427, 0.0562231, 0.849365, 0.582891, 0.0896831, 0.31189, 0.524075}

To get the second nonzero element from each row:

m /. {0 | 0. -> Sequence[]} /. {} | {_} -> Sequence[] /. {_?NumberQ, x_, ___} :> x
{0.949761, 0.841579, 0.0275406, 0.500705}

Total then does the summing.

$\endgroup$

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.